【问题标题】:VBA Shell and Wait with Exit CodeVBA Shell 并等待退出代码
【发布时间】:2021-02-05 16:19:31
【问题描述】:

我正在打包一个办公应用程序 (VBA),它调用 C# 控制台应用程序来执行应用程序的一些繁重工作(大型模拟程序)。我希望能够让 VBA 应用程序等待控制台应用程序完成,并从控制台应用程序中检索退出代码。我已经能够做到前者,但还没有能够从应用程序中检索退出代码。有什么方法可以让我使用像

Diagnostics.Process.Start(filePath)

我在 VB 中看到过这一点,但不确定 VBA。否则,还有其他建议吗?

【问题讨论】:

    标签: vba shell


    【解决方案1】:

    查看WaitForSingleObjectGetExitCodeProcess 函数。

    示例用法:

    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
    

    【讨论】:

    • 我不确定我是否遵循。我正在寻找 VBA 函数来从 C# 控制台应用程序中检索退出代码,这似乎是相反的方式。
    • 这些是 Windows API 调用,您可以在 VBA 应用程序中使用它们。
    • 很抱歉,我会进一步调查。谢谢
    • 这就是我要找的。非常感谢。我确实有两个问题。一、方法中Cmd变量的作用是什么,好像没有在任何地方使用。二,对 DLLErrorText 的调用是您创建的自定义函数吗?再次感谢
    • 嗨,我已经更新了解决方案,很抱歉它只是部分完成,我忘记了!
    【解决方案2】:

    此功能已包含在 ShellAndWait 函数中。

    写得很好here

    【讨论】:

    • 感谢您的文章。我过去曾对此进行过审查;它不会从被调用的应用程序返回退出代码。它仅根据外壳应用程序是否成功终止返回一个代码,它不考虑应用程序发送的退出代码。例如,如果控制台应用程序找不到文件,它会以退出代码 1 终止,但是 shell 和等待代码将返回成功,因为应用程序正确终止。
    • 啊,我的错,我没有仔细审查它。不过不用担心,我认为詹姆斯在上面。
    猜你喜欢
    • 2018-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 2017-06-06
    • 1970-01-01
    • 2015-03-12
    相关资源
    最近更新 更多