共用方式為


判斷命令介面的處理序何時結束

當您在 Visual Basic for Applications (VBA) 程式中執行 Shell 函式時,它會以非同步方式啟動可執行程式,並將控制權傳回給程式。 此殼層程式會以獨立於程序以外的方式繼續執行,直到您將其關閉為止。

如果程序需要等待殼層處理序結束,您可以使用 Windows API 輪詢應用程式的狀態,不過這不是很有效率。 如果程序需要等待殼層處理序結束,您可以使用 Windows API 輪詢應用程式的狀態,不過這不是很有效率。

本主題會說明一個更有效率的方法。 Windows API 所整合的功能可以讓應用程式持續等待,直到殼層處理序完成為止。 若要使用這些功能,您必須要有殼層處理序的常式,所以要以 CreateProcess 函數取代 Shell 函數來啟動您的殼層程式。

建立殼層處理常式

若要建立可定址的處理序,請使用 CreateProcess 函數來啟動殼層應用程式。 CreateProcess 函數會透過傳遞的參數提供殼層應用程式的處理序控點給您的程式。

等候殼層進程結束

使用 CreateProcess 函數取得處理常式之後,可以將此控制代碼傳遞給 WaitForSingleObject 函數。 此時,VBA 程序會暫停執行,直到殼層處理序結束為止。

若要建立一個使用 CreateProcess 函數執行 Windows 記事本應用程式的 VBA 程序,便需要進行下列步驟。 此程式碼會示範如何使用 Windows API 的 CreateProcessWaitForSingleObject 函數等待殼層處理程序結束,然後再繼續執行。

CreateProcess 函數很複雜,所以在此範例程式碼會封裝在一個稱為 ExecCmd 的函數中。 ExecCmd 需要用到一個參數,也就是要執行的應用程式命令列。

  1. 請建立一個標準模組,然後在宣告區段輸入下面數行:

    Option Explicit 
    
    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 PROCESS_INFORMATION 
    hProcess As Long 
    hThread As Long 
    dwProcessID As Long 
    dwThreadID As Long 
    End Type 
    
    Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _ 
    hHandle As Long, ByVal dwMilliseconds As Long) As Long 
    
    Private Declare Function CreateProcessA Lib "kernel32" (ByVal _ 
    lpApplicationName As Long, 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 Long, _ 
    lpStartupInfo As STARTUPINFO, lpProcessInformation As _ 
    PROCESS_INFORMATION) As Long 
    
    Private Declare Function CloseHandle Lib "kernel32" (ByVal _ 
    hObject As Long) As Long 
    
    Private Const NORMAL_PRIORITY_CLASS = &H20& 
    Private Const INFINITE = -1& 
    
    
  2. 在模組中貼入下列程式碼:

    Public Sub ExecCmd(cmdline As String) 
    Dim proc As PROCESS_INFORMATION 
    Dim start As STARTUPINFO 
    Dim ReturnValue As Integer 
    
    ' Initialize the STARTUPINFO structure: 
    start.cb = Len(start) 
    
    ' Start the shelled application: 
    ReturnValue = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, _ 
    NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc) 
    
    ' Wait for the shelled application to finish: 
    Do 
    ReturnValue = WaitForSingleObject(proc.hProcess, 0) 
    DoEvents 
    Loop Until ReturnValue <> 258 
    
    ReturnValue = CloseHandle(proc.hProcess) 
    End Sub
    
  3. 若要測試函式,請在 [即時運算] 視窗中貼上下列程式碼,然後按Enter。 記事本隨即啟動。 片刻之後,關閉 [記事本]。 [記事本] 關閉時會出現訊息方塊。

    ExecCmd "NOTEPAD.EXE": MsgBox "Process Finished" 
    

支援和意見反應

有關於 Office VBA 或這份文件的問題或意見反應嗎? 如需取得支援服務並提供意見反應的相關指導,請參閱 Office VBA 支援與意見反應