Friday, March 07, 2008 7:41 PM
kkchan
Run application and wait (RunAs)
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.