2013-04-11 16 views
17

sto correndo un semplice comando di shell in Excel VBA che esegue un file batch in una directory specificata come di seguito:Attendere comando di shell per completare

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

A volte il file batch potrebbe richiedere più tempo su alcuni computer per eseguire e ci sono codice VBA che dipende dal completamento del file batch. So che è possibile impostare un timer di attesa come di seguito:

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

Ma questo potrebbe non funzionare su alcuni computer che sono troppo lenti. C'è un modo per dire a Excel in modo sistematico di procedere con il resto del codice VBA fino al dopo lo che la shell ha finito di funzionare?

+0

vedere http://stackoverflow.com/a/1439241/1176601 (WaitForSingleObject) – Aprillion

risposta

39

Utilizzare la WScript.Shell invece, perché ha una waitOnReturn opzione:

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 

(Idea copiato da Wait for Shell to finish, then format cells - synchronously execute a command)

+1

in .net, ma non in VBA ... –

+1

Ok, modificato per utilizzare WScript.Shell. –

+0

Dall'aggiornamento dal 2010 al 2013 (e spostando il file .xlam in C: \ Programmi \ Microsoft Office 15 \ root \ office15 \ Library \) non posso più lanciare file .exe usando questo metodo. Sto assumendo alcune autorizzazioni per i file - ma ho esplicitamente aggiunto me stesso come controllo completo (anch'io sono un membro degli amministratori, che sembrava avere già tutti i diritti), ma ricevo comunque un errore: l'applicazione non è stata in grado di iniziare correttamente (0xc000007b). Fare clic su OK per chiudere l'applicazione. Qualche idea/suggerimento? – Terry

0

È possibile che il BATCH crei un file al termine e VBA attenda fino a quando il file non viene creato? O hai un batch eliminare un flag-file quando è finito e VBA aspetta fino a quando il flagfile non è andato?

0

O collegano il guscio di un oggetto, hanno il processo batch sospendere il guscio oggetto (uscita) e il codice VBA continua una volta l'oggetto shell = Nothing?

Oppure dare un'occhiata a questo: Capture output value from a shell command in VBA?

0

Questo è quello che io uso per avere VB attesa per il processo di completamento prima di continuare. Non l'ho scritto e non mi sono preso credito.

E 'stato offerto in qualche altro forum aperto e funziona molto bene per me:

Le seguenti dichiarazioni sono necessari per il RunShell subroutine:

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) 
+1

Questo codice non funziona in VBA in quanto non è definito alcun RunShell – CrazyHorse

-2

Dim WSH come nuovo WshShell

chdir "Directory di file batch"

wsh.eseguire "percorso completo del file batch", vbNormalFocus, vero

Done Figlio

+0

Non capisco la tua risposta .... –

1

che avete proposto con un cambio alla parentesi al comando Esegui funzionato bene con VBA per me

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 
2

Salvare il file bat su "C: \ WINDOWS \ system32" e utilizzare il codice qui sotto si sta lavorando

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 
4

Aggiungere il seguente Sub:

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

Se si aggiunge un riferimento a C:\Windows\system32\wshom.ocx è anche possibile utilizzare:

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

Questa versione dovrebbe essere più efficiente.

Problemi correlati