Initial: flux text FoxBin2Prg (git urmareste .??2 in-arbore, binarele VFP git-ignored)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
399
clase/process.vc2
Normal file
399
clase/process.vc2
Normal file
@@ -0,0 +1,399 @@
|
||||
*--------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
* (EN) AUTOGENERATED - ATTENTION!! - NOT INTENDED FOR EXECUTION!! USE ONLY FOR MERGING CHANGES AND STORING WITH SCM TOOLS!!
|
||||
*--------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
*< FOXBIN2PRG: Version="1.21" SourceFile="process.vcx" CPID="1252" /> (Solo para binarios VFP 9 / Only for VFP 9 binaries)
|
||||
*
|
||||
*
|
||||
DEFINE CLASS api_apprun AS custom
|
||||
*< CLASSDATA: Baseclass="custom" Timestamp="" Scale="Pixels" Uniqueid="" />
|
||||
|
||||
*<DefinedPropArrayMethod>
|
||||
*m: checkprocessexitcode
|
||||
*m: extractdword
|
||||
*m: getprochandle
|
||||
*m: killproc
|
||||
*m: launchapp
|
||||
*m: launchappandwait
|
||||
*m: parseprocessinfostruc
|
||||
*m: releasehandle
|
||||
*p: iccommandline
|
||||
*p: icerrormesage
|
||||
*p: icerrormessage
|
||||
*p: iclaunchdir
|
||||
*p: icwindowmode
|
||||
*p: inprocesshandle
|
||||
*p: inthreadhandle
|
||||
*</DefinedPropArrayMethod>
|
||||
|
||||
PROTECTED inprocesshandle,inthreadhandle
|
||||
*<PropValue>
|
||||
iccommandline = space(0)
|
||||
icerrormesage = (space(0))
|
||||
iclaunchdir = (space(0))
|
||||
icwindowmode = (space(0))
|
||||
inprocesshandle = .NULL.
|
||||
inthreadhandle = .NULL.
|
||||
Name = "api_apprun"
|
||||
*</PropValue>
|
||||
|
||||
PROCEDURE checkprocessexitcode
|
||||
LPARAMETER nProcessToCheck
|
||||
IF TYPE('nProcessToCheck') # 'N'
|
||||
nProcessToCheck = this.inProcessHandle
|
||||
ENDIF
|
||||
DECLARE SHORT GetExitCodeProcess IN Win32API AS CheckExitCode ;
|
||||
INTEGER hProcess, ;
|
||||
INTEGER @lpdwExitCode
|
||||
LOCAL nExitCode
|
||||
nExitCode = 0
|
||||
IF ! ISNULL(nProcessToCheck)
|
||||
IF CheckExitCode(nProcessToCheck, @nExitCode) = 1
|
||||
* We retrieved an exit code (259 means still running, tho
|
||||
RETURN nExitCode
|
||||
ELSE
|
||||
* Process did not exist in process table - no exit status
|
||||
this.icErrorMessage = 'Process to check not in active Process Table'
|
||||
RETURN NULL
|
||||
ENDIF
|
||||
ELSE
|
||||
this.icErrorMessage = 'NULL process handle passed to CheckProcessExitCode'
|
||||
RETURN NULL
|
||||
ENDIF
|
||||
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE Destroy
|
||||
WITH THIS
|
||||
IF TYPE('.inThreadHandle') = 'N' AND NOT ISNULL(.inThreadHandle)
|
||||
.ReleaseHandle(.inThreadHandle)
|
||||
.inThreadHandle = NULL
|
||||
ENDIF
|
||||
IF TYPE('.inProcessHandle') = 'N' AND NOT ISNULL(.inProcessHandle)
|
||||
.ReleaseHandle(.inProcessHandle)
|
||||
.inProcessHandle = NULL
|
||||
ENDIF
|
||||
ENDWITH
|
||||
DODEFAULT()
|
||||
|
||||
|
||||
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE extractdword
|
||||
LPARAMETER cStringToExtractFrom
|
||||
IF TYPE('cStringToExtractFrom')='C' AND LEN(cStringToExtractFrom) >= 4
|
||||
RETURN (((ASC(SUBST(cStringToExtractFrom,4,1))*256) + ;
|
||||
ASC(SUBST(cStringToExtractFrom,3,1)))*256 + ;
|
||||
ASC(SUBST(cStringToExtractFrom,2,1)))*256 + ;
|
||||
ASC(LEFT(cStringToExtractFrom,1))
|
||||
ELSE
|
||||
this.icErrorMessage = 'Invalid DWORD string passed for conversion'
|
||||
RETURN NULL
|
||||
ENDIF
|
||||
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE getprochandle
|
||||
RETURN this.inProcessHandle
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE Init
|
||||
*
|
||||
* API_AppRun - use the CreateProcess() API to launch, monitor, and kill an Executable
|
||||
*
|
||||
* Properties:
|
||||
*
|
||||
* inProcessHandle (P) ProcessHandle generated by CreateProcess()
|
||||
* inThreadHandle (P) ThreadHandle for First Thread of inProcessHandle
|
||||
* icErrorMessage R/O Error Message Detailed Description
|
||||
* icCommandLine R/W Command Line to launch via CreateProcess()
|
||||
* icLaunchDir R/W Directory to use as startup dir for CreateProcess()
|
||||
* icWindowMode R/W Window Start Mode, one of (HID, NOR, MIN, MAX) or empty
|
||||
* defaults to empty, the default for the executable is used
|
||||
*
|
||||
* Methods:
|
||||
*
|
||||
* Init (O) Command Line, (O) Start Dir, (O) Window Start Mode
|
||||
* If sent, the icCommandLine, icLaunchDir and icWindowMode properties are set
|
||||
* Destroy
|
||||
* LaunchApp // Launches .icComandLine from .icLaunchDir in .icWindowMode
|
||||
* // NB - at least .icCommandLine must be set to not fail
|
||||
* RETURNS: BOOL, check icErrorMessage on .F.
|
||||
* LaunchAppAndWait // Call LaunchApp() and wait on either user termination or process termination
|
||||
* RETURNS: BOOL, check icErrorMessage on .F.
|
||||
* CheckProcessExitCode (O) Process handle to check, defaults to .inProcessHandle
|
||||
* // Get Process named by Process Handle's Exit Code (259 = still running)
|
||||
* RETURNS: Integer, check on NULL, if NULL, check icErrorMessage
|
||||
* ExtractDWORD (R) String to convert
|
||||
* //Converts a 4 byte or longer string to a DWORD integer
|
||||
* RETURNS: Integer, check on NULL, if NULL arg was invalid
|
||||
* KillProc (O) Process handle to Terminate, defaults to .inProcessHandle
|
||||
* // Kills specified process using TerminateProcess()
|
||||
* RETURNS: BOOL, check icErrorMessage on .F.
|
||||
* GetProcHandle // Returns the Process Handle for the current Process
|
||||
* // NB - only useful for KillProc(), since Destroy will close the handle
|
||||
* RETURNS: Integer, check for NULL, if NULL no process was started yet
|
||||
* ParsePROCESSINFOStruc // Pulls the Process Handle and Thread Handle from the PROCESSINFO structure
|
||||
* // Only used internally
|
||||
* ReleaseHandle (R) Handle to Close
|
||||
* // Invokes CloseHandle() to explicitly release process/thread handles
|
||||
* // Only used internally, but can be externalized
|
||||
* RETURNS: BOOL, check .icErrorMessage if false
|
||||
*
|
||||
LPARAMETERS tcCommandLine, tcLaunchDir, tcWindowMode
|
||||
* Set up the environment for the object
|
||||
LOCAL aDirTest[1,5]
|
||||
WITH THIS
|
||||
.icErrorMessage = ''
|
||||
.icCommandLine = ''
|
||||
.icLaunchDir = ''
|
||||
.icWindowMode = ''
|
||||
.inProcessHandle = NULL
|
||||
.inThreadHandle = NULL
|
||||
* store parameters if passed
|
||||
IF TYPE('tcCommandLine') = 'C'
|
||||
.icCommandLine = ALLTRIM(tcCommandLine)
|
||||
ENDIF
|
||||
DO CASE
|
||||
CASE TYPE('tcLaunchDir') # 'C'
|
||||
* Not a character expression - ignore
|
||||
CASE ADIR(aDirTest, tcLaunchDir, 'D') # 1
|
||||
* Either directory doesn't exist, or there's a wildcard in the expression
|
||||
.icErrorMessage = 'Invalid directory for startup passed to Init method'
|
||||
OTHERWISE
|
||||
* Valid directory - save it
|
||||
.icLaunchDir = ALLTRIM(tcLaunchDir)
|
||||
ENDCASE
|
||||
DO CASE
|
||||
CASE TYPE('tcWindowMode') # 'C'
|
||||
* Not passed in or not valid type
|
||||
CASE INLIST(PADR(UPPER(ALLTRIM(tcWindowMode)),3),'NOR','MIN','MAX','HID')
|
||||
* Valid mode - set it
|
||||
.icWindowMode = PADR(UPPER(ALLTRIM(tcWindowMode)),3)
|
||||
OTHERWISE
|
||||
* No a valid character string
|
||||
IF ! EMPTY(.icErrorMessage)
|
||||
.icErrorMessage = .icErrorMessage + ' & '
|
||||
ENDIF
|
||||
.icErrorMessage = .icErrorMessage + CHR(10) + CHR(13) + 'Invalid WindowMode passed to Init Method'
|
||||
ENDCASE
|
||||
ENDWITH
|
||||
RETURN .T.
|
||||
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE killproc
|
||||
LPARAMETER nProcessToKill
|
||||
IF TYPE('nProcessToKill') # 'N'
|
||||
nProcessToKill = This.inProcessHandle
|
||||
ENDIF
|
||||
DECLARE SHORT TerminateProcess IN WIN32API AS KillProc ;
|
||||
INTEGER hProcess, ;
|
||||
INTEGER uExitCode
|
||||
LOCAL nResult
|
||||
IF ! ISNULL(nProcessToKill)
|
||||
nResult = KillProc(nProcessToKill,0)
|
||||
this.icErrorMessage = IIF(nResult = 0, 'TerminateProcess() could not kill process handle requested','')
|
||||
ELSE
|
||||
this.icErrorMessage = 'NULL handle passed to KillProc()'
|
||||
nResult = 0
|
||||
ENDIF
|
||||
RETURN (nResult = 1)
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE launchapp
|
||||
LOCAL cCommandLine, uFromDir, cWindowMode
|
||||
WITH This
|
||||
.icErrorMessage = ''
|
||||
IF TYPE('.icCommandLine') # 'C'
|
||||
* Command line must be a character string
|
||||
.icErrorMessage = 'icCommand line must be set, and a string value'
|
||||
RETURN .F.
|
||||
ELSE
|
||||
cCommandLine = ALLTRIM(.icCommandLine)
|
||||
ENDIF
|
||||
IF TYPE('.icLaunchDir') # 'C' OR EMPTY(.icLaunchDir)
|
||||
* If not a character string, pass a null pointer, defaulting to Current Working Dir
|
||||
uFromDir = 0
|
||||
ELSE
|
||||
* Otherwise, null pad the string
|
||||
uFromDir = .icLaunchDir + CHR(0)
|
||||
ENDIF
|
||||
IF TYPE('.icWindowMode') # 'C'
|
||||
* If not passed, set to null string
|
||||
cWindowMode = ''
|
||||
ELSE
|
||||
* Translate the passed window mode to uppercase
|
||||
cWindowMode = UPPER(.icWindowMode)
|
||||
ENDIF
|
||||
* 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 in method
|
||||
* 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 method, 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
|
||||
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
|
||||
|
||||
LOCAL 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 cWindowMode = 'HID'
|
||||
* Hide - use STARTF_USESHOWFLAG and value of 0
|
||||
cStartUpInfo = CHR(68) + ;
|
||||
REPL(CHR(0),43) + ;
|
||||
CHR(1) + ;
|
||||
REPL(CHR(0),23)
|
||||
CASE cWindowMode = '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 cWindowMode = '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 cWindowMode = '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)
|
||||
OTHERWISE
|
||||
* Use default of application
|
||||
cStartUpInfo = CHR(68) + REPL(CHR(0),67)
|
||||
ENDCASE
|
||||
LOCAL lResult
|
||||
lResult = CrPr( 0, ;
|
||||
cCommandLine, ;
|
||||
0, 0, 0, 0, 0, ;
|
||||
uFromDir, ;
|
||||
@cStartUpInfo, ;
|
||||
@cProcessInfo)
|
||||
* Strip the handles from the PROCESS_INFORMATION structure and save in private properties
|
||||
IF lResult = 1
|
||||
.ParseProcessInfoStruc(cProcessInfo)
|
||||
RETURN .T.
|
||||
ELSE
|
||||
.icErrorMessage = 'Process Specified by icCommandLine could not be started'
|
||||
RETURN .F.
|
||||
ENDIF
|
||||
ENDWITH
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE launchappandwait
|
||||
#Define cnINFINITE 0xFFFFFFFF
|
||||
#Define cnHalfASecond 500 && milliseconds
|
||||
#Define cnTimedOut 258 && 0x0102
|
||||
|
||||
Local loEx As Exception
|
||||
|
||||
* We need some API calls, declare here
|
||||
* GetCurrentProcess returns the pseudohandle of the current process (ie VFP instance)
|
||||
Declare Integer GetCurrentProcess In WIN32API As GetCurrProc
|
||||
* WaitForIdleInput waits until the application is instantiated and at it's event loop
|
||||
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
|
||||
* Save the Process handle if any and the result of LaunchApp
|
||||
* Fire the app and save the process handle
|
||||
Local uResult
|
||||
uResult = 0
|
||||
With This
|
||||
.icErrorMessage = ''
|
||||
If .LaunchApp()
|
||||
uResult = 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(.inProcessHandle, cnHalfASecond) = cnTimedOut
|
||||
* Give us an out in case the other app hangs - let
|
||||
Try
|
||||
* 01.10.2008
|
||||
* nu stiu de ce da eroare la inkey()
|
||||
lnInkey = Inkey()
|
||||
*!* StrToFile('inkey: ' + Transform(lnInkey) + ' type: ' + Type('lnInkey'),"c:\inkey.txt")
|
||||
If lnInkey = 27
|
||||
* Still running but we aren't waiting - return a -1 as a warning
|
||||
.icErrorMessage = 'Process started but user did not wait on termination'
|
||||
uResult = 0
|
||||
Exit
|
||||
Endif
|
||||
Catch To loEx
|
||||
* do nothing
|
||||
Endtry
|
||||
* 01.10.2008 ^
|
||||
Enddo
|
||||
Else
|
||||
* Return 0 to indicate failure
|
||||
uResult = 0
|
||||
Endif
|
||||
Endwith
|
||||
Return (uResult = 1)
|
||||
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE parseprocessinfostruc
|
||||
LPARAMETER cProcessInfoStructure
|
||||
WITH This
|
||||
.inProcessHandle = .ExtractDWORD(cProcessInfoStructure)
|
||||
.inThreadHandle = .ExtractDWORD(SUBST(cProcessInfoStructure,5))
|
||||
ENDWITH
|
||||
|
||||
|
||||
ENDPROC
|
||||
|
||||
PROTECTED PROCEDURE releasehandle
|
||||
LPARAMETER nHandleToRelease
|
||||
LOCAL nResult
|
||||
* Use CloseHandle(), returns a BOOL; 0 = False
|
||||
DECLARE SHORT CloseHandle IN Win32API AS CloseHand INTEGER nHandleToClose
|
||||
IF TYPE('nHandleToRelease') = 'N' AND ! ISNULL(nHandleToRelease)
|
||||
nResult = CloseHand(nHandleToRelease)
|
||||
this.icErrorMessage = IIF(nResult = 0, 'TerminateProcess() failed to close handle','')
|
||||
ELSE
|
||||
this.icErrorMessage = 'Invalid handle passed to ReleaseHandle() invocation'
|
||||
nResult = 0
|
||||
ENDIF
|
||||
RETURN (nResult = 1)
|
||||
ENDPROC
|
||||
|
||||
ENDDEFINE
|
||||
Reference in New Issue
Block a user