>************************************************************ >* FUNCTION DeclareDLLs() >************************************************************ >* Author............: VCS Developers Team >* Project...........: Visual Collections System >* Created...........: 01/02/2006 12:22:27 >* Copyright.........: (c) Jzanus, 2006 >*) Description.......: >* Calling Samples...: >* Parameter List....: >* Major change list.: >function DeclareDLLs() >* 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 > >declare long CloseHandle in Kernel32 long hObject > >endfunc >******************************************************************** >* Description.......: LaunchAppAndWait >* Calling Samples...: >* lcDir=justpath(oJC.OutTable) >* if file('C:\MAILERS\MP4W32.exe') >* pStatus=LaunchAppAndWait('C:\MAILERS\MP4W32.exe',lcDir) >* else >* =messagebox('Can not find Mailers program!',48,'Error') >* pStatus=0 >* endif >* Parameter List....: tcCommandLine, tuFromDir, tcWindowMode >* 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 > >if vartype(m.tcCommandLine) # 'C' >* Command line must be a character string > return 0 >endif > >#define cnINFINITE 0xFFFFFFFF >#define cnHalfASecond 500 && milliseconds >#define cnTimedOut 0x0102 >if vartype(m.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 = m.tuFromDir + chr(0) >endif >if vartype(m.tcWindowMode) # 'C' > >* If not passed, set to null string > tcWindowMode = '' > >else > >* Translate the passed window mode to uppercase > tcWindowMode = upper(m.tcWindowMode) > >endif > >local nStartedProcessHandle, uResult, cProcessInfo, cStartUpInfo, hThread > >* 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 = replicate(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 m.tcWindowMode = 'HIDE' > >* Hide - use STARTF_USESHOWFLAG and value of 0 > cStartUpInfo = chr(68) + ; > replicate(chr(0),43) + ; > chr(1) + ; > replicate(chr(0),23) > >case m.tcWindowMode = 'NOR' > >* Normal - use STARTF_USESHOWFLAG and value of 1 > cStartUpInfo = chr(68) + ; > replicate(chr(0),43) + ; > chr(1) + ; > replicate(chr(0),3) + ; > chr(1) + ; > replicate(chr(0),19) > >case m.tcWindowMode = 'MIN' > >* Minimize - use STARTF_USESHOWFLAG and value of 2 > cStartUpInfo = chr(68) + ; > replicate(chr(0),43) + ; > chr(1) + ; > replicate(chr(0),3) + ; > chr(2) + ; > replicate(chr(0),19) > >case m.tcWindowMode = 'MAX' > >* Maximize - use STARTF_USESHOWFLAG and value of 3 > cStartUpInfo = chr(68) + ; > replicate(chr(0),43) + ; > chr(1) + ; > replicate(chr(0),3) + ; > chr(3) + ; > replicate(chr(0),19) > >* Other options exist - see WINBASE.H for values > >otherwise > >* Use default of application > cStartUpInfo = chr(68) + replicate(chr(0),67) > >endcase > >* Do it now! >uResult = CrPr( 0, ; > m.tcCommandLine, ; > 0, 0, 0, 0, 0, ; > m.tuFromDir, ; > @cStartUpInfo, ; > @cProcessInfo) > >if m.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)) > >** should be this > nStartedProcessHandle = (((asc(subst(m.cProcessInfo,4,1))*256^3) + ; > asc(subst(m.cProcessInfo,3,1)))*256^2 + ; > asc(subst(m.cProcessInfo,2,1)))*256 + ; > asc(left(m.cProcessInfo,1)) > >** Get Thread handle also >** Both handles must then be closed using CloseHandle() API > hThread = (((asc(subst(m.cProcessInfo,8,1))*256^3) + ; > asc(subst(m.cProcessInfo,7,1)))*256^2 + ; > asc(subst(m.cProcessInfo,6,1)))*256 + ; > asc(left(m.cProcessInfo,5)) > >* =WaitInpIdle(GetCurrProc(),cnINFINITE) > >* Wait for the idle of the new/child process not the idle of the current process > WaitInpIdle( m.nStartedProcessHandle, cnINFINITE ) > > do while WaitOnAppExit(m.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 > >** Process & Thread Handles must be closed >** or else it will remains in the system > > if (m.nStartedProcessHandle != 0) > CloseHandle(m.nStartedProcessHandle ) > endif > > if (m.hThread != 0) > CloseHandle(m.hThread ) > endif >endif > >return m.uResult >