tags:

views:

1178

answers:

2

I am wrapping up an office application (VBA) that makes a call to a C# console application to perform some of the heavy lifting for the application (large simulation program). I would like to be able to have the VBA application wait for the console application to complete as well as retreive the exit code from the console application. I have been able to do the former, but have yet to be able to retrieve the exit code from the application. Is there any way that I can use something like

Diagnostics.Process.Start(filePath)

I have seen this in VB but not sure about VBA. Otherwise, any other suggestions?

+4  A: 

Have a look at WaitForSingleObject and GetExitCodeProcess functions.

Example Usage:

Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId 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

Public Const INFINITE = &HFFFF
Public Const PROCESS_ALL_ACCESS = &H1F0FFF

Sub RunApplication(ByVal Cmd as String)

    lTaskID = Shell(Cmd, vbNormalFocus)
    //Get process handle
    lPID = OpenProcess(PROCESS_ALL_ACCESS, True, lTaskID)
    If lPID Then
        //Wait for process to finish
        Call WaitForSingleObject(lPID, INFINITE)
        //Get Exit Process
        If GetExitCodeProcess(lPID, lExitCode) Then
            //Received value
            MsgBox "Successfully returned " & lExitCode, vbInformation
        Else
            MsgBox "Failed: " & DLLErrorText(Err.LastDllError), vbCritical
        End If
    Else
        MsgBox "Failed: " & DLLErrorText(Err.LastDllError), vbCritical
    End If
    lTaskID = CloseHandle(lPID)
End Sub

Public Function DLLErrorText(ByVal lLastDLLError As Long) As String
    Dim sBuff As String * 256
    Dim lCount As Long
    Const FORMAT_MESSAGE_ALLOCATE_BUFFER = &H100, FORMAT_MESSAGE_ARGUMENT_ARRAY = &H2000
    Const FORMAT_MESSAGE_FROM_HMODULE = &H800, FORMAT_MESSAGE_FROM_STRING = &H400
    Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000, FORMAT_MESSAGE_IGNORE_INSERTS = &H200
    Const FORMAT_MESSAGE_MAX_WIDTH_MASK = &HFF

    lCount = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS, 0, lLastDLLError, 0&, sBuff, Len(sBuff), ByVal 0)
    If lCount Then
        DLLErrorText = Left$(sBuff, lCount - 2) \\Remove line feeds
    End If

End Function
James
I am not sure that I follow. I am looking for the VBA function to retreive the exit code from the C# console application, this seems like it is the other way around.
Irwin M. Fletcher
those are Windows API calls, you can use them in a VBA application.
James
Sorry about that, I will look into it further. Thanks
Irwin M. Fletcher
This is what I was looking for. Thanks a lot. I do have two questions. One, what is the purpose of the Cmd variable in the method, it does not appear to be used anywhere. Two, is the call to DLLErrorText a custom function that you created? Thanks again
Irwin M. Fletcher
Hi, I have updated the solution, apologies it was only partially completed and I forgot all about it!
James
+1  A: 

This functionality has been wrapped up in the ShellAndWait function.

Excellent write up on it here.

Mark
Thanks for the article. I had reviewed this in the past; it does not return the exit code from the called application. It only returns a code based on if the shelled application terminates successfully, it does not account for the exit code the application sent. For example, if the console application cannot find a file it terminates with an exit code of 1, however the shell and wait code will return as successful because the application terminated correctly.
Irwin M. Fletcher
Ahh, my bad, I didn't review it close enough. No worries, though, I think James has it above.
Mark