• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 175
  • Last Modified:

Getting a Return Code from an Application

Below is the code I use to Launch a process then sit and listen for it to be finished..  I would like to get the true return code of the application I am executing.

It is always returning 0, and I have broken an application that if I were to use ws.run to launch it, it would return a non-zero. HOw can I get the true return code of the application that is finished executing..

The function I am launching is Launch.

Option Explicit

Private Type PROCESS_INFORMATION
        hProcess As Long
        hThread As Long
        dwProcessId As Long
        dwThreadId As Long
End Type
Private Type SECURITY_ATTRIBUTES
        nLength As Long
        lpSecurityDescriptor As Long
        bInheritHandle As Long
End Type

Private Type STARTUPINFO
        cb As Long
        lpReserved As String
        lpDesktop As String
        lpTitle As String
        dwX As Long
        dwY As Long
        dwXSize As Long
        dwYSize As Long
        dwXCountChars As Long
        dwYCountChars As Long
        dwFillAttribute As Long
        dwFlags As Long
        wShowWindow As Integer
        cbReserved2 As Integer
        lpReserved2 As Long
        hStdInput As Long
        hStdOutput As Long
        hStdError As Long
End Type

Private Type SHELLEXECUTEINFO
  cbSize As Long
  fMask As Long
  hwnd As Long
  lpVerb As String
  lpFile As String
  lpParameters As String
  lpDirectory As String
  nShow As Long
  hInstApp As Long
  lpIDList As Long
  lpClass As String
  hkeyClass As Long
  dwHotKey As Long
  hIcon As Long
  hProcess As Long
End Type

Const SEE_MASK_NOCLOSEPROCESS = &H40
Const SW_SHOWNORMAL = 1
Const SW_HIDE = 0

Private Declare Function ShellExecuteEx Lib "shell32.dll" Alias "ShellExecuteExA" (lpExecInfo As _
  SHELLEXECUTEINFO) As Long

Const SE_ERR_FNF = 2
Const SE_ERR_NOASSOC = 31
Const INFINITE = &HFFFF
Const WAIT_TIMEOUT = &H102

Private Const MAX_PATH = 260
Private Type FILETIME
        dwLowDateTime As Long
        dwHighDateTime As Long
End Type

Private Type WIN32_FIND_DATA
        dwFileAttributes As Long
        ftCreationTime As FILETIME
        ftLastAccessTime As FILETIME
        ftLastWriteTime As FILETIME
        nFileSizeHigh As Long
        nFileSizeLow As Long
        dwReserved0 As Long
        dwReserved1 As Long
        cFileName As String * MAX_PATH
        cAlternate As String * 14
End Type

Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" _
        (ByVal lpApplicationName As String, ByVal lpCommandLine As String, ByVal _
         lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
         ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
         ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _
         lpStartupInfo As STARTUPINFO, lpProcessInformation As _
         PROCESS_INFORMATION) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Long, lpSource As Any, ByVal dwMessageId As Long, ByVal dwLanguageId As Long, ByVal lpBuffer As String, ByVal nSize As Long, Arguments As Long) As Long

' ***************************************************************************************
Private LaunchReturnCode As Long ' Return code from launching and running an application
Private Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
'Private Const INFINITE = &HFFFF

Private Const WAIT_ABANDONED = &H80
Private Const WAIT_OBJECT_0 = 0
'Private Const WAIT_TIMEOUT = &H102
Private Const INVALID_HANDLE_VALUE = -1


Public Function Launch(Program As String, ProgParams As String, retval As Long, Msg As String) As Boolean

On Error GoTo Launch_Error

  Dim sei As SHELLEXECUTEINFO  ' structure used by the function
  'Dim retval As Long  ' return value
 
  ' Load the information needed to open C:\Docs\readme.txt
  ' into the structure.
  With sei
      ' Size of the structure
      .cbSize = Len(sei)
      ' Use the optional hProcess element of the structure.
      .fMask = SEE_MASK_NOCLOSEPROCESS
      ' Handle to the window calling this function.
      .hwnd = frmReboot.hwnd
      ' The action to perform: open the file.
      .lpVerb = "open"
      ' The file to open.
      .lpFile = Program
      ' No additional parameters are needed here.
      .lpParameters = ProgParams
      ' The default directory -- not really necessary in this case.
      .lpDirectory = TargetDirectory
      ' Simply display the window.
      .nShow = SW_HIDE
      ' The other elements of the structure are either not used
      ' or will be set when the function returns.
  End With
 
  ' Open the file using its associated program.
 
  retval = ShellExecuteEx(sei)
  MsgBox retval
  If retval = 0 Then
      ' The function failed, so report the error.  Err.LastDllError
      ' could also be used instead, if you wish.
      Select Case sei.hInstApp
      Case SE_ERR_FNF
          MsgBox "File not found"
      Case SE_ERR_NOASSOC
           MsgBox "no program is associated to this file"
      Case Else
          MsgBox "An unexpected error occured."
      End Select
  Else
      ' Wait for the opened process to close before continuing.  Instead
      ' of waiting once for a time of INFINITE, this example repeatedly checks to see if the
      ' is still open.  This allows the DoEvents VB function to be called, preventing
      ' our program from appearing to lock up while it waits.
      Do
          DoEvents
          retval = WaitForSingleObject(sei.hProcess, 0)
      Loop While retval = WAIT_TIMEOUT
      MsgBox retval
     
  End If








Exit Function

Launch_Error:

Msg = "LAUNCH ERROR: " & Err.Description
Launch = False
Exit Function

End Function
0
tchous
Asked:
tchous
1 Solution
 
webJoseCommented:
Also use this flag:

Private Const SEE_MASK_FLAG_DDEWAIT As Long = &H100

Also, in the case of retval <> 0 (the function ShellExecuteex succeeded), you must check for sei.hInstApp.  If it is less than or equal to 32, the process was not shelled.

Finally, after the wait loop you must call GetExitCodeProcess to get the return code you are looking for.
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now