******************************************************************** * Description.......: LaunchAppAndWait * Calling Samples...: * Parameter List....: * Created by........: Ed Rauh * Modified by.......: ******************************************************************** FUNCTION LaunchAppAndWait LPARAMETERS tcCommandLine, tuFromDir, tcWindowMode * tcCommandLine (R) - command line to launch * tuFromDir (O) - Run from directory (default - CWD) * tcWindowMode (O) - Start Application Window mode, one of (HIDE, MIN, MAX, NOR) * (default - default setting of application) * Returns: * 0 = CreateProcess didn't start what was asked * 1 = Process ran to completion * -1= Process started but user aborted wait. Danger - app is still running AFAIK #DEFINE cnINFINITE 0xFFFFFFFF #DEFINE cnHalfASecond 500 && milliseconds #DEFINE cnTimedOut 0x0102 * We need some API calls, declare here * GetCurrentProcess() returns the pseudohandle of the current process DECLARE INTEGER GetCurrentProcess IN WIN32API AS GetCurrProc * WaitForIdleInput() waits until the target process is idle for input DECLARE INTEGER WaitForInputIdle IN WIN32API AS WaitInpIdle ; INTEGER nProcessHandle, ; INTEGER nWaitForDuration * WaitForSingleObject() waits until the handle in parm 1 is signalled * or the timeout period expires DECLARE INTEGER WaitForSingleObject IN WIN32API AS WaitOnAppExit ; INTEGER hProcessHandle, ; INTEGER dwTimeOut * This API call does the work. The parameters are as follows: * lpszModuleName - ptr-> file name of module to execute. Since we aren't launching .CPLs, do not use * lpszCommandLine - ptr-> command to execute, as passed to us * lpSecurityAttributesProcess - ptr-> SECURITY_ATTRIBUTES structure for Process. Pass a null pointer * lpSecurityAttributesThread - ptr-> SECURITY_ATTRIBUTES structure for first thread. Pass a null pointer * bInheritHandles - whether or not chlid inherits parent handles. Since no SECURITY_ATTRIBUTES passed, default to FALSE * dwCreateFlags - Process Creation Mode flag set. We use the default mode at normal priority, ie 0 * lpvEnvironment - ptr-> a set of environment strings as if a MULTI_SZ. We don't set, so pass a null pointer * lpszStartupDir - ptr-> the starting directory. If none provided to us, pass a null pointer * lpStartInfo - ptr-> a STARTUPINFO structure. We use one structure member at times. * lpProcessInfo - ptr-> a PROCESS_INFORMATION structure, used to return PID/PHANDLE detail. * We use one member on return DECLARE SHORT CreateProcess IN WIN32API AS CrPr ; STRING lpszModuleName, ; STRING @lpszCommandLine, ; STRING lpSecurityAttributesProcess, ; STRING lpSecurityAttributesThread, ; SHORT bInheritHandles, ; INTEGER dwCreateFlags, ; STRING lpvEnvironment, ; STRING lpszStartupDir, ; STRING @lpStartInfo, ; STRING @lpProcessInfo IF TYPE('tcCommandLine') # 'C' * Command line must be a character string RETURN 0 ENDIF IF TYPE('tuFromDir') # 'C' * If not a character string, pass a null pointer, defaulting to Current Working Dir tuFromDir = 0 ELSE * Otherwise, null pad the string tuFromDir = tuFromDir + CHR(0) ENDIF IF TYPE('tcWindowMode') # 'C' * If not passed, set to null string tcWindowMode = '' ELSE * Translate the passed window mode to uppercase tcWindowMode = UPPER(tcWindowMode) ENDIF LOCAL nStartedProcessHandle, uResult, cProcessInfo, cStartUpInfo * Make default Structures for the CreateProcess call * * ProcessInfo - 4 bytes, a Process handle, a Thread Handle, a (DWORD) ProcessId and a (DWORD) ThreadID * we save the Process handle and return it to caller in tnReturnProcessHandle cProcessInfo = REPL(CHR(0),16) * StartUpInfo is a 68 byte long complex structure; we either have 68 bytes with a cb member (byte 1) 68 * or with cb of 68, dwFlag low order byte (byte 45) of 1, and low order byte wShowWindow (byte 49) set to * the SW_ value appropriate for the Window Mode desired. DO CASE CASE tcWindowMode = 'HIDE' * Hide - use STARTF_USESHOWFLAG and value of 0 cStartUpInfo = CHR(68) + ; REPL(CHR(0),43) + ; CHR(1) + ; REPL(CHR(0),23) CASE tcWindowMode = 'NOR' * Normal - use STARTF_USESHOWFLAG and value of 1 cStartUpInfo = CHR(68) + ; REPL(CHR(0),43) + ; CHR(1) + ; REPL(CHR(0),3) + ; CHR(1) + ; REPL(CHR(0),19) CASE tcWindowMode = 'MIN' * Minimize - use STARTF_USESHOWFLAG and value of 2 cStartUpInfo = CHR(68) + ; REPL(CHR(0),43) + ; CHR(1) + ; REPL(CHR(0),3) + ; CHR(2) + ; REPL(CHR(0),19) CASE tcWindowMode = 'MAX' * Maximize - use STARTF_USESHOWFLAG and value of 3 cStartUpInfo = CHR(68) + ; REPL(CHR(0),43) + ; CHR(1) + ; REPL(CHR(0),3) + ; CHR(3) + ; REPL(CHR(0),19) * Other options exist - see WINBASE.H for values OTHERWISE * Use default of application cStartUpInfo = CHR(68) + REPL(CHR(0),67) ENDCASE * Do it now! uResult = CrPr( 0, ; tcCommandLine, ; 0, 0, 0, 0, 0, ; tuFromDir, ; @cStartUpInfo, ; @cProcessInfo) IF uResult = 1 * CreateProcess() started our app, but we have to wait until it finishes loading * Strip the process handle from the PROCESS_INFORMATION structure nStartedProcessHandle = (((ASC(SUBST(cProcessInfo,4,1))*256) + ; ASC(SUBST(cProcessInfo,3,1)))*256 + ; ASC(SUBST(cProcessInfo,2,1)))*256 + ; ASC(LEFT(cProcessInfo,1)) * It's been launched; wait until we're idling along =WaitInpIdle(GetCurrProc(),cnINFINITE) * As long as the other process exists, wait for it DO WHILE WaitOnAppExit(nStartedProcessHandle, cnHalfASecond) = cnTimedOut * Give us an out in case the other app hangs - lets the user quit via IF INKEY() = 27 * Still running but we aren't waiting - return a -1 as a warning uResult = -1 EXIT ENDIF ENDDO ELSE * Return 0 to indicate failure uResult = 0 ENDIF RETURN uResult