Welcome To The Home Of The Visual FoxPro Experts  
home. signup. forum. archives. search. google. articles. downloads. faq. members. weblogs. file info. rss.
 From: Lou Harris
  Where is Lou Harris?
 Kansas City
 Kansas - United States
 Lou Harris
 To: Cheryl B
  Where is Cheryl B?
 Xenia
 Ohio - United States
 Cheryl B
 Tags
Subject: RE: WinExec Failed
Thread ID: 21943 Message ID: 21944 # Views: 23 # Ratings: 0
Version: Visual FoxPro 6 Category: General VFP Topics
Date: Saturday, April 05, 2003 12:55:07 AM         
   


> Hello All!
>
> I need to interface a VFP6.0 program with a FW2.6 program. I'm using RUN right now, but I've seen the posts where that isn't a good idea. I agree, because we sometimes get "WinExec Failed, Code=24" on some W2K computers. In fact, we can have the program run fine for a while, but once we get the error, it seems to be "broke" forever.
>
>
PUBLIC gcSYSMemFile, gcPath
> STORE FILENAME(M.SY_TempDir + "\" + SYS(3) + ".TMP") TO gcSYSMemFile
> SAVE ALL LIKE SY_* TO (M.gcSYSMemFile)
> STORE "F:" + M.gcSYSMemFile TO gcSYSMemFile
> STORE "P:" + SET("PATH") TO gcPath
> STORE FULLPATH("VISVF2FW.EXE") TO gcEXE
> STORE STUFF(M.gcEXE, AT(".EXE", M.gcExe), 4, "") TO gcExe

>
> And the actual run command is:
>
  RUN /N &gcEXE &gcSYSMemFile &gcPath "R:VRR001.EXE" -T

>
> Any suggestions on how to "fix" the WinExec error? And any suggestions on the "best" way to do what I want? (Okay, besides converting all the FPW2.6 code to VFP... we're working on that! This is just a workaround until that is completed.)
>
> Cheryl A Bellucci
> TRIAD GOVERNMENTAL SYSTEMS, INC
> (who now uses her Foxite lunchbox to carry lunch to work!)

I have a little program that uses the CreateProcess API call to launch a program. Here is a snippet of the main functions:

FUNCTION NewLaunch()
  LPARAMETERS tcFile, tlWaitForIt
  *  To run Notepad, you'd do the following
  *    NewLaunch("NOTEPAD.EXE C:\TEMP\TEXTFILE.TXT",.F.)
  LOCAL cFile, nProcHand, llSuccess
  llSuccess = .F.
  tlWaitForIt = IIF(EMPTY(tlWaitForIt), .F., .T.)

  nProcHand = NULL
  cFile = tcFile
  IF NOT LaunchApp(cFile,'','NOR', @nProcHand)
    *  Failed to run!
  ELSE
    llSuccess = .T.
    DECLARE INTEGER Sleep IN WIN32API ;
      INTEGER nMilliseconds
    
    *  To check on your instance later:
    DO WHILE NOT ISNULL(nProcHand)
      nResult = CheckProcessExitCode(nProcHand)
      DO CASE
      CASE ISNULL(nResult)
        *  Process is no longer in the system process table, so it isn't running
        nProcHand = .NULL.
      CASE nResult = 259
        *  Still running
        IF M.tlWaitForIt
          =Sleep(200)
        ELSE
          nProcHand = .NULL.
        ENDIF
      OTHERWISE
        *  It's no longer running, and terminated with the exit code value in nResult
        *  You should release the handle now to release the process object from system memory
        * by calling CloseHandle() like this
        DECLARE SHORT CloseHandle IN Win32API AS CloseHand INTEGER nHandleToClose
        =CloseHand(nProcHand)
        nProcHand = .NULL.
      ENDCASE
    ENDDO
  ENDIF
  RETURN M.llSuccess
ENDFUNC

FUNCTION LaunchApp
  LPARAMETERS cCommandLine, uFromDir, cWindowMode, nReturnProcessHandle
  cCommandLine = ALLTRIM(cCommandLine)
  IF TYPE('uFromDir') # 'C' OR EMPTY(uFromDir)
    *  If not a character string, pass a null pointer, defaulting to Current Working Dir
    uFromDir = 0
  ELSE
    *  Otherwise, null pad the string
    uFromDir = uFromDir + CHR(0)
  ENDIF
  IF TYPE('cWindowMode') # 'C'
    *  If not passed, set to null string
    cWindowMode = ''
  ELSE
    *  Translate the passed window mode to uppercase
    cWindowMode = UPPER(cWindowMode)
  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 -  struc, 4 DWORDs, a Process Handle, a Thread Handle, a ProcessID and a ThreadID
  *          we save the Process and Thread Handles in member properties to ensure that
  *          they are properly disposed at Destroy by CloseHandle()

  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
    nReturnProcessHandle = ParseProcessInfoStruc(cProcessInfo)
    RETURN .T.
  ELSE
    RETURN .F.
  ENDIF
ENDFUNC

FUNCTION ParseProcessInfoStruc
  LPARAMETER cProcessInfoStructure
  LOCAL nHandle
  *  Throw away the thread handle, we don't need it, and it eats an entry in the system
  *  object table until you close the handle
  DECLARE SHORT CloseHandle IN Win32API AS CloseHand INTEGER nHandleToClose
  =CloseHand(ExtractDWORD(SUBST(cProcessInfoStructure,5)))
  RETURN ExtractDWORD(cProcessInfoStructure)
ENDFUNC

FUNCTION ExtractDWORD
  LPARAMETER cStringToExtractFrom
  RETURN (((ASC(SUBST(cStringToExtractFrom,4,1))*256) + ;
    ASC(SUBST(cStringToExtractFrom,3,1)))*256 + ;
    ASC(SUBST(cStringToExtractFrom,2,1)))*256 + ;
    ASC(LEFT(cStringToExtractFrom,1))
ENDFUNC

FUNCTION CheckProcessExitCode
  LPARAMETER nProcessToCheck
  IF TYPE('nProcessToCheck') # 'N'
    RETURN NULL
  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
      RETURN NULL
    ENDIF
  ELSE
    RETURN NULL
  ENDIF
ENDFUNC



Lou Harris
lharris@epiqsystems.com
Software Engineer, EPIQ Systems, Inc.
http://www.epiqsystems.com

COMPLETE THREAD

WinExec Failed Posted by Cheryl Bellucci @ 4/4/2003 10:49:01 PM
RE: WinExec Failed Posted by Lou Harris @ 4/5/2003 12:55:07 AM