Дождитесь завершения команды оболочки [duplicate]

21

Я запускаю простую команду оболочки в Excel VBA, которая запускает пакетный файл в указанном каталоге, как показано ниже:

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

Иногда пакетный файл может занять больше времени на каком-либо компьютере для запуска, и происходит продолжение кода VBA, зависящего от командного файла, для завершения работы. Я знаю, что вы можете установить таймер ожидания, как показано ниже:

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

Но это может не работать на некотором компьютере, который слишком медленный. Есть ли способ систематически сообщить Excel, чтобы продолжить работу с остальным кодом VBA, пока после не закончит работу оболочки?

    
задан user974047 11.04.2013 в 16:46
источник
  • см. stackoverflow.com/a/1439241/1176601 (WaitForSingleObject) –  Aprillion 11.04.2013 в 16:51

8 ответов

49

Вместо этого используйте WScript.Shell, потому что у него есть опция 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

(Идея скопирована из Подождите, пока Shell закончит работу, а затем отформатирует ячейки - синхронно выполните команду )

    
ответ дан Nate Hekman 11.04.2013 в 16:52
  • в .net, но не в VBA ... –  K_B 11.04.2013 в 16:55
  • Хорошо, изменено для использования WScript.Shell. –  Nate Hekman 11.04.2013 в 17:08
  • С момента обновления с 2010 по 2013 год (и перемещение .xlam-файла в C: \ Program Files \ Microsoft Office 15 \ root \ office15 \ Library) Я больше не могу запускать файлы .exe с помощью этого метода. Я принимаю некоторые мягкие разрешения на доступ к файлам, но я явно добавил себя как полный контроль (я тоже являюсь членом администраторов, у которого уже были полные права), но я все равно получаю сообщение об ошибке: приложение не смогло начните правильно (0xc000007b). Нажмите «ОК», чтобы закрыть приложение. Любые идеи / предложения? –  Terry 27.09.2013 в 17:38
  • Эта строка в ответе Nate: wsh.Run («C: \ folder \ runbat.bat», windowStyle, waitOnReturn) дает ошибку компиляции: «Ожидаемое:« = ». Когда скобки удалены, она работает: wsh. Запустите «C: \ folder \ runbat.bat», windowStyle, waitOnReturn. Я не уверен, относится ли это к делу, но я запускаю Win8 и Excel 2013. –  user2946432 01.11.2013 в 22:12
  • не работает для меня beacause из «Метод« Запуск »объекта« IWshShell3 »с ошибкой» номер ошибки -2147024894 –  Qbik 26.09.2015 в 13:05
Показать остальные комментарии
5

Добавьте следующий Sub:

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

Если вы добавите ссылку на C:\Windows\system32\wshom.ocx , вы также можете использовать:

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

Эта версия должна быть более эффективной.

    
ответ дан Anonymous 13.09.2015 в 16:59
2

Сохраните файл bat на «C: \ WINDOWS \ system32» и используйте ниже код, который он работает.

   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   
    
ответ дан Asam 09.10.2014 в 09:26
1

то, что вы предложили с изменением в скобках в команде «Запуск», отлично работало с VBA для меня

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
    
ответ дан dadj 18.07.2014 в 14:20
0

Может ли BATCH создать файл, когда он закончен, и VBA подождать, пока этот файл не будет создан? Или пакетное удаление флагового файла, когда оно закончено, и VBA ждет, пока файл флага не исчезнет?

    
ответ дан Magoo 11.04.2013 в 16:51
0

Либо свяжите оболочку с объектом, пакетное задание завершает объект оболочки (exit), и код VBA продолжается после объекта оболочки = ничего?

Или взгляните на это: Захват выходного значения из команды оболочки в VBA?     

ответ дан K_B 11.04.2013 в 16:52
0

Это то, что я использую, чтобы VB дождался завершения процесса до продолжения. Я не писал этого и не беру кредит.

Он был предложен на каком-то другом открытом форуме и очень хорошо работает для меня:

Следующие запросы необходимы для подпрограммы 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)
    
ответ дан geek0 05.03.2014 в 22:27
  • Этот код не работает в VBA, поскольку не определено RunShell –  CrazyHorse 08.05.2014 в 18:07
-2

Dim wsh как новый wshshell

chdir "Каталог пакетного файла"

wsh.run «Полный путь к пакетному файлу», vbnormalfocus, true

Готовый сын

    
ответ дан Borkman 08.05.2014 в 18:05
  • Не понимаю ваш ответ .... –  Paul Lo 08.05.2014 в 18:23