判斷命令介面的處理序何時結束
當您在 Visual Basic for Applications (VBA) 程式中執行 Shell 函式時,它會以非同步方式啟動可執行程式,並將控制權傳回給程式。 此殼層程式會以獨立於程序以外的方式繼續執行,直到您將其關閉為止。
如果程序需要等待殼層處理序結束,您可以使用 Windows API 輪詢應用程式的狀態,不過這不是很有效率。 如果程序需要等待殼層處理序結束,您可以使用 Windows API 輪詢應用程式的狀態,不過這不是很有效率。
本主題會說明一個更有效率的方法。 Windows API 所整合的功能可以讓應用程式持續等待,直到殼層處理序完成為止。 若要使用這些功能,您必須要有殼層處理序的常式,所以要以 CreateProcess 函數取代 Shell 函數來啟動您的殼層程式。
建立殼層處理常式
若要建立可定址的處理序,請使用 CreateProcess 函數來啟動殼層應用程式。 CreateProcess 函數會透過傳遞的參數提供殼層應用程式的處理序控點給您的程式。
等候殼層進程結束
使用 CreateProcess 函數取得處理常式之後,可以將此控制代碼傳遞給 WaitForSingleObject 函數。 此時,VBA 程序會暫停執行,直到殼層處理序結束為止。
若要建立一個使用 CreateProcess 函數執行 Windows 記事本應用程式的 VBA 程序,便需要進行下列步驟。 此程式碼會示範如何使用 Windows API 的 CreateProcess 及 WaitForSingleObject 函數等待殼層處理程序結束,然後再繼續執行。
CreateProcess 函數很複雜,所以在此範例程式碼會封裝在一個稱為 ExecCmd 的函數中。 ExecCmd 需要用到一個參數,也就是要執行的應用程式命令列。
請建立一個標準模組,然後在宣告區段輸入下面數行:
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&
在模組中貼入下列程式碼:
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
若要測試函式,請在 [即時運算] 視窗中貼上下列程式碼,然後按Enter。 記事本隨即啟動。 片刻之後,關閉 [記事本]。 [記事本] 關閉時會出現訊息方塊。
ExecCmd "NOTEPAD.EXE": MsgBox "Process Finished"
支援和意見反應
有關於 Office VBA 或這份文件的問題或意見反應嗎? 如需取得支援服務並提供意見反應的相關指導,請參閱 Office VBA 支援與意見反應。