Déterminer la fin d’un processus Shell

Lorsque vous exécutez la fonction Shell dans une procédure Visual Basic pour Applications (VBA), elle démarre un programme exécutable de façon asynchrone et retourne le contrôle à la procédure. Ce programme Shell continue de s'exécuter indépendamment de votre procédure jusqu'à ce que vous la fermiez.

Si votre procédure doit attendre la fin du processus Shell, vous pouvez utiliser l'API de Windows pour chercher le statut de l'application, mais cela n'est pas très efficace. Cette rubrique vous explique une méthode plus efficace.

L'API de Windows intègre une fonctionnalité qui permet à votre application d'attendre la fin d'un processus Shell. Pour utiliser ces fonctions, vous devez disposer d'une poignée sur le processus Shell. Pour cela, utilisez la fonction CreateProcess au lieu de la fonction Shell pour commencer votre programme Shell.

Créer le processus interpréteur de commandes

Pour créer un processus adressable, utilisez la fonction CreateProcess pour démarrer votre application Shell. La fonction CreateProcess donne à votre programme le handle du processus Shell via un de ses paramètres transmis.

Attendez la fin du processus shellé

Vous pouvez transmettre cette poignée à la fonction WaitForSingleObject après avoir utilisé la fonction CreateProcess pour obtenir un descripteur de processus. Votre procédure VBA suspend alors son exécution jusqu'à la fin du processus Shell.

Les étapes suivantes sont nécessaires pour générer une procédure VBA qui utilise la fonction CreateProcess pour exécuter l’application Windows Notepad. Ce code montre comment utiliser les fonctions CreateProcess et WaitForSingleObject de l'API de Windows pour attendre la fin d'un processus Shell avant de reprendre l'exécution.

La syntaxe de la fonction CreateProcess étant complexe, dans l’exemple de code, elle est encapsulée dans une fonction appelée ExecCmd. ExecCmd prend un paramètre, la ligne de commande de l’application à exécuter.

  1. Créez un module standard et collez les lignes suivantes dans la section Déclarations :

    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. Collez le code suivant dans le module :

    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. Pour tester la fonction, collez le code suivant dans la fenêtre Exécution et appuyez sur Entrée. Le Bloc-notes démarre. Après un instant, fermez le Bloc-notes. La boîte de message s’affiche lorsque le Bloc-notes se ferme.

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

Assistance et commentaires

Avez-vous des questions ou des commentaires sur Office VBA ou sur cette documentation ? Consultez la rubrique concernant l’assistance pour Office VBA et l’envoi de commentaires afin d’obtenir des instructions pour recevoir une assistance et envoyer vos commentaires.