Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How can I get the DOS Errorlevel from executed program?

API Functions

How can I get the DOS Errorlevel from executed program?

by  wgcs  Posted    (Edited  )
This seems easy to do, but it requires you to get the process handle of the launched program (which could be an .EXE, or a .BAT, as in the example below).

In VFP:
Code:
lcBatchFile = FULLPATH('MyBatFile.BAT')
lnExitCode = RunExitCode( getenv('COMSPEC'), "/c "+lcBatchFile )

In File MyBatFile.BAT:
Code:
@echo off
cls
call 3rdparty.exe

if errorlevel 10 goto error10
if errorlevel 5 goto error5
if errorlevel 0 goto error0

gotoend

:error10
echo Error 10 - Invalid command line syntax.
EXIT 10
gotoend

:error5
echo Error 5 - Unable to read image file.
EXIT 5
gotoend

:error0
echo Error0 - all ok
EXIT 0

:end
EXIT 0

In file RunExitCode.prg:
Code:
**********************************************************
* Program: RunExitCode.PRG                               *
* Author : William GC Steinford                          *
* Date   : Nov 2002                                      *
**********************************************************
FUNCTION RunExitCode
LPARAMETERS pcProgFile, pcCmdLine
* ?RunExitCode("c:\winnt\system32\cmd.exe", " /c dir c:\*.* > \temp\dir.txt")
DECLARE INTEGER CreateProcess IN kernel32; 
    STRING   lpApplicationName,; 
    STRING   lpCommandLine,; 
    INTEGER  lpProcessAttributes,; 
    INTEGER  lpThreadAttributes,; 
    INTEGER  bInheritHandles,; 
    INTEGER  dwCreationFlags,; 
    INTEGER  lpEnvironment,; 
    STRING   lpCurrentDirectory,; 
    STRING   lpStartupInfo,; 
    STRING @ lpProcessInformation 

DECLARE LONG WaitForSingleObject in win32api ;
  INTEGER hHandle, LONG dwMilliseconds

DECLARE INTEGER GetExitCodeProcess in win32api ;
  INTEGER hProcess, INTEGER @ nExitCode

#DEFINE SW_SHOW      5
#DEFINE STILL_ACTIVE 0x103

cStartInfo = GetStartupInfo()

cProcessInfo = repl( chr(0), 12 )

*!*    typedef struct _PROCESS_INFORMATION { 
*!*        HANDLE hProcess; 
*!*        HANDLE hThread; 
*!*        DWORD dwProcessId; 
*!*        DWORD dwThreadId; 
*!*    } PROCESS_INFORMATION;


if 0=CreateProcess( pcProgFile, pcCmdLine, ;
                    0,0,0,0,0,0, cStartInfo, @cProcessInfo )
  ?"Could not create process"                    
  RETURN -1
endif

hProcess = Buf2dword( left( cProcessInfo, 4 ) )
?"Process handle = "+Tran(hProcess)
* // Give the process time to execute and finish
nExitCode = STILL_ACTIVE
do while nExitCode=STILL_ACTIVE
  WaitForSingleObject(hProcess, 5000) && 5 seconds
  if 0<>GetExitCodeProcess(hProcess, nExitCode)
    do case
      case nExitCode=STILL_ACTIVE
        ?"Process is still active"
      otherwise
        ?"Exit code = "+ tran( nExitCode )
    endcase
  else 
    ?"GetExitCodeProcess() failed"
    nExitCode = -2
  endif
enddo

RETURN nExitCode

* * *
* dword is compatible with LONG
FUNCTION  num2dword (lnValue) 
#DEFINE m0       256 
#DEFINE m1     65536 
#DEFINE m2  16777216 
    LOCAL b0, b1, b2, b3 
    b3 = Int(lnValue/m2) 
    b2 = Int((lnValue - b3*m2)/m1) 
    b1 = Int((lnValue - b3*m2 - b2*m1)/m0) 
    b0 = Mod(lnValue, m0) 
RETURN Chr(b0)+Chr(b1)+Chr(b2)+Chr(b3) 
* * *
* dword is compatible with LONG
FUNCTION  num2word (lnValue) 
RETURN Chr(MOD(m.lnValue,256)) + CHR(INT(m.lnValue/256)) 
* * * 
FUNCTION  buf2word (lcBuffer) 
RETURN Asc(SUBSTR(lcBuffer, 1,1)) + ; 
    Asc(SUBSTR(lcBuffer, 2,1)) * 256 
* * *
FUNCTION  buf2dword (lcBuffer)  
RETURN;  
    Asc(SUBSTR(lcBuffer, 1,1)) + ;  
    Asc(SUBSTR(lcBuffer, 2,1)) * 256 +;  
    Asc(SUBSTR(lcBuffer, 3,1)) * 65536 +;  
    Asc(SUBSTR(lcBuffer, 4,1)) * 16777216  
ENDFUNC  

* Thanks to www.news2news.com for Startupinfo structure definition
PROCEDURE  getStartupInfo 
* creates the STARTUP structure to specify main window 
* properties if a new window is created for a new process 

*| typedef struct _STARTUPINFO {  
*|     DWORD   cb;                4 
*|     LPTSTR  lpReserved;        4 
*|     LPTSTR  lpDesktop;         4 
*|     LPTSTR  lpTitle;           4 
*|     DWORD   dwX;               4 
*|     DWORD   dwY;               4 
*|     DWORD   dwXSize;           4 
*|     DWORD   dwYSize;           4 
*|     DWORD   dwXCountChars;     4 
*|     DWORD   dwYCountChars;     4 
*|     DWORD   dwFillAttribute;   4 
*|     DWORD   dwFlags;           4 
*|     WORD    wShowWindow;       2 
*|     WORD    cbReserved2;       2 
*|     LPBYTE  lpReserved2;       4 
*|     HANDLE  hStdInput;         4 
*|     HANDLE  hStdOutput;        4 
*|     HANDLE  hStdError;         4 
*| } STARTUPINFO, *LPSTARTUPINFO; total: 68 bytes 

#DEFINE STARTF_USESHOWWINDOW   1 
#DEFINE SW_SHOWMAXIMIZED       3 

RETURN  num2dword(68) +; 
    num2dword(0) + num2dword(0) + num2dword(0) +; 
    num2dword(0) + num2dword(0) + num2dword(0) + num2dword(0) +; 
    num2dword(0) + num2dword(0) + num2dword(0) +; 
    num2dword(STARTF_USESHOWWINDOW) +; 
    num2word(SW_SHOWMAXIMIZED) +; 
    num2word(0) + num2dword(0) +; 
    num2dword(0) + num2dword(0) + num2dword(0)
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top