retval macro from ejecutar comando excel shell vba batch-file

excel - macro - Espere a que el comando de shell se complete



vba excel ejecutar cmd (8)

¿Podría hacer que BATCH cree un archivo cuando termine y VBA espere hasta que se cree ese archivo? ¿O tiene que eliminar por lotes un archivo de bandera cuando haya terminado y VBA espera hasta que el archivo de bandera se haya ido?

Estoy ejecutando un simple comando de shell en Excel VBA que ejecuta un archivo por lotes en un directorio específico como el siguiente:

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

A veces, el archivo por lotes puede tardar más en ejecutarse en alguna computadora, y hay un código de VBA que depende del archivo por lotes para terminar de ejecutarse. Sé que puedes configurar un temporizador de espera como el siguiente:

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

Pero eso podría no funcionar en algunas computadoras que son muy lentas. ¿Hay una manera de decirle a Excel que continúe con el resto del código VBA hasta que el shell haya terminado de ejecutarse?


Agregue el siguiente Sub:

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

Si agrega una referencia a C:/Windows/system32/wshom.ocx también puede usar:

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

Esta versión debería ser más eficiente.


Dim wsh como nuevo wshshell

chdir "Directorio de archivo por lotes"

wsh.run "Ruta completa del archivo por lotes", vbnormalfocus, true

Hijo hecho


Esto es lo que uso para que VB espere a que se complete el proceso antes de continuar. No escribí esto y no tomo crédito.

Se ofreció en algún otro foro abierto y funciona muy bien para mí:

Las siguientes declaraciones son necesarias para la subrutina 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)


Guarde el archivo bat en "C: / WINDOWS / system32" y use el siguiente código que funciona

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




lo que propuso con un cambio en el paréntesis en el comando Ejecutar funcionó bien con VBA para mí

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