Freigeben über


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.

  1. 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& 
    
    
  2. 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
    
  3. 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.