Bestimmen, wann ein Shellprozess beendet wird
Beim Ausführen der Shell-Funktion in einer Visual Basic for Applications (VBA)-Prozedur startet diese auf asynchrone Weise ein ausführbares Programm und gibt die Steuerung an die Prozedur zurück. Das Shell-Programm wird unabhängig von Ihrer Prozedur weiter ausgeführt, bis Sie es schließen.
Wenn Ihre Prozedur auf das Ende des Shell-Prozesses warten muss, können Sie die Windows-API verwenden, um den Status der Anwendung abzufragen. Dies ist aber nicht sehr effizient. In diesem Thema wird eine effizientere Methode beschrieben.
Die Windows-API verfügt über eine integrierte Funktionalität, mit der Ihre Anwendung warten kann, bis ein Shell-Prozess abgeschlossen ist. Wenn Sie diese Funktionen verwenden möchten, müssen Sie über ein Handle für den Shell-Prozess verfügen. Verwenden Sie zu diesem Zweck die CreateProcess-Funktion anstelle der Shell-Funktion, um Ihr Shell-Programm zu starten.
Erstellen des Shell-Prozesses
Verwenden Sie zum Erstellen eines adressierbaren Prozesses die CreateProcess-Funktion, um die Shell-Anwendung zu starten. Die CreateProcess-Funktion stellt dem Programm das Prozesshandle des Shell-Prozesses über einen der übergebenen Parameter bereit.
Warten auf das Ende des Shell-Prozesses
Nachdem Sie mithilfe der CreateProcess-Funktion ein Prozesshandle abgerufen haben, können Sie dieses Handle an die WaitForSingleObject-Funktion übergeben. Dies bewirkt, dass Ihre VBA-Prozedur die Ausführung anhält, bis der Shell-Prozess beendet ist.
Die folgenden Schritte sind erforderlich, um eine VBA-Prozedur zu erstellen, die die CreateProcess-Funktion zum Ausführen der Anwendung Windows Editor verwendet. Dieser Code zeigt, wie Sie die Windows-API CreateProcess und WaitForSingleObject-Funktionen verwenden, um zu warten, bis ein Shell-Prozess endet, bevor die Ausführung fortgesetzt wird.
Die Syntax der CreateProcess-Funktion ist komplex. Im Beispielcode ist sie daher in einer Funktion mit der Bezeichnung ExecCmd gekapselt. ExecCmd verwendet einen Parameter, die Befehlszeile der Anwendung, zum Ausführen.
Erstellen Sie ein Standardmodul und fügen Sie die folgenden Zeilen in den Deklarationsbereich ein:
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&
Fügen Sie den folgenden Code in das Modul ein:
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
Fügen Sie zum Testen der Funktion den folgenden Code in das Direktfenster ein, und drücken Sie die EINGABETASTE. Der Editor wird gestartet. Schließen Sie nach einem Moment Editor. Das Meldungsfeld wird angezeigt, wenn Editor geschlossen wird.
ExecCmd "NOTEPAD.EXE": MsgBox "Process Finished"
Support und Feedback
Haben Sie Fragen oder Feedback zu Office VBA oder zu dieser Dokumentation? Unter Office VBA-Support und Feedback finden Sie Hilfestellung zu den Möglichkeiten, wie Sie Support erhalten und Feedback abgeben können.