************************************************************ * 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