web-dev-qa-db-fra.com

Attendez que la commande Shell se termine

J'exécute une commande Shell simple dans Excel VBA qui exécute un fichier de commandes dans un répertoire spécifié, comme ci-dessous: 

Dim strBatchName As String
strBatchName = "C:\folder\runbat.bat"
Shell strBatchName

Parfois, l’exécution du fichier de commandes peut prendre plus de temps sur un ordinateur et le code VBA en cours dépend de l’exécution du fichier de commandes. Je sais que vous pouvez définir un délai d'attente comme ci-dessous:

Application.Wait Now + TimeSerial(0, 0, 5)

Mais cela pourrait ne pas fonctionner sur certains ordinateurs trop lents. Existe-t-il un moyen d'indiquer systématiquement à Excel de continuer à utiliser le reste du code VBA jusqu'à ce que après le shell ait été exécuté?

28
user974047

Utilisez plutôt WScript.Shell, car il a une option waitOnReturn:

Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1

wsh.Run "C:\folder\runbat.bat", windowStyle, waitOnReturn

(Idée copiée à partir de Attendez que Shell se termine, puis formatez les cellules - exécutez une commande de manière synchrone )

57
Nate Hekman

Ajouter le sous suivant:

Sub SyncShell(ByVal Cmd As String, ByVal WindowStyle As VbAppWinStyle)
VBA.CreateObject("WScript.Shell").Run Cmd, WindowStyle, True
End Sub

Si vous ajoutez une référence à C:\Windows\system32\wshom.ocx, vous pouvez également utiliser:

Sub SyncShell(ByVal Cmd As String, ByVal WindowStyle As VbAppWinStyle)
Static wsh As New WshShell
wsh.Run Cmd, WindowStyle, True
End Sub

Cette version devrait être plus efficace.

5
Anonymous

Enregistrez le fichier bat sur "C:\WINDOWS\system32" et utilisez le code ci-dessous, il fonctionne 

   Dim wsh As Object
   Set wsh = VBA.CreateObject("WScript.Shell")
   Dim waitOnReturn As Boolean: waitOnReturn = True
   Dim windowStyle As Integer: windowStyle = 1
   Dim errorCode As Integer

   errorCode = wsh.Run("runbat.bat", windowStyle, waitOnReturn)

If errorCode = 0 Then
    'Insert your code here
Else
    MsgBox "Program exited with error code " & errorCode & "."
End If   
3
Asam

ce que vous avez proposé avec un changement de parenthèse dans la commande Exécuter a bien fonctionné avec VBA pour moi

Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
Dim waitOnReturn As Boolean: waitOnReturn = True
Dim windowStyle As Integer: windowStyle = 1
Dim errorCode As Integer
wsh.Run "C:\folder\runbat.bat", windowStyle, waitOnReturn
1
dadj

Pourriez-vous demander à BATCH de créer un fichier à la fin et de laisser VBA attendre la création de ce fichier? Ou avez-vous supprimé par lots un fichier de drapeau une fois que c'est terminé et que VBA attend que le fichier de drapeau disparaisse?

0
Magoo

Vous pouvez soit relier le shell à un objet, demander au travail par lots de mettre fin à l'objet shell (quitter) et laisser le code VBA continuer une fois que l'objet shell = rien?

Ou jetez un œil à ceci: Capturer la valeur de sortie d’une commande Shell dans VBA?

0
K_B

C’est ce que j’avais l'habitude d'avoir VB d'attendre que le processus soit terminé avant de poursuivre… Je ne l'ai pas écrit et je ne m'en félicite pas. 

Il a été offert dans un autre forum ouvert et fonctionne très bien pour moi:

Les déclarations suivantes sont nécessaires pour le sous-programme RunShell:

Option Explicit

Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long

Private Declare Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As Long, lpExitCode As Long) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Const PROCESS_QUERY_INFORMATION = &H400

Private Const STATUS_PENDING = &H103&

'then in your subroutine where you need to Shell:

RunShell (path and filename or command, as quoted text)
0
geek0