Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Launch app and wait without RUN
Message
From
14/09/1998 19:32:37
 
 
To
All
General information
Forum:
Visual FoxPro
Category:
Windows API functions
Title:
Launch app and wait without RUN
Miscellaneous
Thread ID:
00136528
Message ID:
00136528
Views:
67
The following code will launch a DOS or Windows executable without using the RUN command; it gives some control over the starting window of the executable at start, and waits pretty reliably on termination, using the Process Handle rather than a Window Handle to test for completion. My thanks to dozens of instances of various applets like NOTEPAD and EDLIN, without whom this code would bnever have been debugged:
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 <Esc>
		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
EMail: EdR@edrauh.com
"See, the sun is going down..."
"No, the horizon is moving up!"
- Firesign Theater


NT and Win2K FAQ .. cWashington WSH/ADSI/WMI site
MS WSH site ........... WSH FAQ Site
Wrox Press .............. Win32 Scripting Journal
eSolutions Services, LLC

The Surgeon General has determined that prolonged exposure to the Windows Script Host may be addictive to laboratory mice and codemonkeys
Next
Reply
Map
View

Click here to load this message in the networking platform