I am changing my application to be Vista compatible. I need to run an external EXE and wait for until it terminate. Beside, I also need to run this EXE with Admin privilege under certain condition.

To run external application and wait till it terminate, I found the code as below.

loShell = CREATEOBJECT("WScript.Shell")
loShell.Run("C:\MyApp\MyApp.exe", 1, 1)

However, it doesn't support elevation.

To run application via elevation process, I can

DECLARE INTEGER ShellExecute IN "Shell32.dll" ;
	INTEGER hwnd, STRING lpVerb, STRING lpFile, STRING lpParameters, ;
	STRING lpDirectory, LONG nShowCmd

ShellExecute(0, "runas", "C:\MyApp\MyApp.exe", "", "", 1)

Unfortunately, ShellExecute() doesn't wait but return control back to calling program immediately.

In order to have both features, I found ShellExecuteEX ...

DECLARE LONG ShellExecuteEx IN Shell32 STRING @SHELLEXECUTEINFO

DECLARE INTEGER WaitForSingleObject IN kernel32;
	INTEGER hHandle, INTEGER dwMilliseconds

LOCAL loSHELLEXECUTEINFO AS SHELLEXECUTEINFO OF SHELLEXECUTEINFO.prg, ;
		lcStructure AS String

loSHELLEXECUTEINFO = NEWOBJECT("SHELLEXECUTEINFO", "SHELLEXECUTEINFO.prg")
loSHELLEXECUTEINFO.fld("lpVerb") = "runas" + CHR(0)
loSHELLEXECUTEINFO.fld("lpFile") = "C:\MyApp\MyApp.exe" + CHR(0)
loSHELLEXECUTEINFO.fld("nShow") = 1
loSHELLEXECUTEINFO.fld("lpParameters") = CHR(0)

**********************************************
* Required in order to get process id returned
**********************************************
loSHELLEXECUTEINFO.fld("fMask") = SEE_MASK_NOCLOSEPROCESS

lcStructure = loSHELLEXECUTEINFO.Structure 

ShellExecuteEx(@lcStructure)
loSHELLEXECUTEINFO.Structure = lcStructure

***********************************************************
* Wait for application termination (-1)
***********************************************************
WaitForSingleObject(loSHELLEXECUTEINFO.fld("hProcess"), -1)

**************************************************************
* Define SHELLEXECUTEINFO strucuture using class Struct
* from http://fox.wikis.com/wc.dll?Wiki~ApiStructureClass~VFP
**************************************************************

DEFINE CLASS SHELLEXECUTEINFO AS Struct OF Struct.prg

	#IF .F.
		LOCAL THIS AS SHELLEXECUTEINFO OF SHELLEXECUTEINFO.prg
	#ENDIF

	PROCEDURE INIT()
	
		THIS.AddField("cbSize", "LONG", 60)
		THIS.AddField("fMask", "LONG", 0)
		THIS.AddField("hwnd", "LONG", 0)
		THIS.AddField("lpVerb", "@STRING", CHR(0))
		THIS.AddField("lpFile", "@STRING", CHR(0))
		THIS.AddField("lpParameters", "@STRING", CHR(0))
		THIS.AddField("lpDirectory", "@STRING", CHR(0))

		THIS.AddField("nShow", "LONG", 0)
		THIS.AddField("hInstApp", "LONG", 0)
		THIS.AddField("lpIDList", "@STRING", CHR(0))
		THIS.AddField("lpClass", "@STRING", CHR(0))
		THIS.AddField("hkeyClass", "@STRING", CHR(0))
		THIS.AddField("dwHotKey", "LONG", 0)
		THIS.AddField("hIcon", "LONG", 0)
		THIS.AddField("hProcess", "LONG", 0)

	ENDPROC	

ENDDEFINE

I used ApiStructureClass to create structure that required by ShellExecuteEx. It makes job much easier.