>******************************************************************** >* 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 >