VBScript-как заставить программу ждать, пока процесс не закончится?

у меня проблема в VBScript, который я использую с макросом VBA/Excel и HTA. Проблема заключается только в VBScript, у меня есть два других компонента, т. е. макрос VBA и интерфейс HTA работают отлично. Но прежде чем я объясню проблему, я думаю, что для вас, чтобы помочь мне, я должен помочь вам понять контекст VBScript.

Итак, в основном все компоненты (VBScript, VBA macro и HTA) являются частями инструмента, который я создаю для автоматизации некоторых ручных работ. Это довольно много идет так:

A-HTA

~~~~~~~~~~~~

  1. пользователь выбирает некоторые файлы из HTA / GUI.
  2. в HTML HTA есть некоторый VBScript в тегах "SCRIPT", который передает пользователям 4 входных файла в качестве аргументов VBScript (выполняется WScript.exe - вы можете обратиться к примечанию № 1 для ясности здесь)
  3. скрипт, назовем это именем MyScript.vbs С этого момента обрабатывает 4 аргумента, 3 из которых конкретные файлы и 4-й путь/папку с несколькими файлами в ней (см. Также примечание № 2 для наглядности)

Б - универсальный.vbs

~~~~~~~~~~~~

  1. именем MyScript.vbs открывает первые 3 аргумента, которые являются файлами Excel. Один из них-а *.xlsm-файл с моим макросом VBA.
  2. именем MyScript.затем vbs использует 4-й аргумент, который является путем к папке, содержащей несколько файлов, и присваивает его переменной для переход к объекту FileSystemObject при вызове GetFolder, т. е.

    ... 'Other code here, irrelevant for this post
    Dim FSO, FLD, strFolder
    ... 'Other code here, irrelevant for this post
    arg4 = args.Item(3)
    strFolder = arg4
    Set FSO = CreateObject("Scripting.FileSystemObject"
    'Get a reference to the folder you want to search
    Set FLD = FSO.GetFolder(strFolder)
    ...
    
  3. отсюда я создаю цикл, чтобы я мог последовательно открывать файлы в папке а затем запустите мой макрос, т. е.

    ...
    Dim strWB4, strMyMacro
    strMyMacro = "Sheet1.my_macro_name"
    
    'loop through the folder and get the file names
    For Each Fil In FLD.Files
    
        Set x4WB = x1.Workbooks.Open(Fil)
    x4WB.Application.Visible = True
    
    x1.Run strMyMacro
    
    x4WB.close
    Next 
    ...
    

обратите внимание, что когда первые 3 файла Excel открыты (управляются кодом до цикла, а не показываются здесь, поскольку у меня нет проблем с этой частью), я должен держать их открытыми.

Это файлы в папка (которая была передана как 4-й аргумент), которая должна последовательно открываться и закрываться. Но между Открытием и закрытием мне нужен VBA/macro (записанный в одном из 3 ранее открытых файлов Excel) для запуска каждый раз цикл повторяется и открывает новый файл из папки (надеюсь, вы следуете - если нет, пожалуйста, дайте мне знать :) ).

проблема в том, что файлы в папке открываются и закрываются, открываются и закрываются, n количество раз (n = # файлов в папке, естественно), не дожидаясь запуска макроса. Это не то, чего я хочу. Я пробовал WScript.оператор sleep с 10-секундной задержкой после ' x1.Запустите оператор strMyMacro, но безрезультатно.

какие идеи?

спасибо, ФК.

Примечания:

1 - Для простоты / ясности вот как:

    strCMD = cmd /c C:windowssystem32wscript.exe myScript.vbs <arg1> <arg2> <arg3> <arg4>
    'FYI - This is run by creating a WShell object, wsObj, and using the .run method, i.e. WShell.run(strCMD)

2 HTA использует кусок JavaScript, который удаляет 4-й входной файл пользователей (HTML: INPUT TYPE= "file") и передает его в VBScript в HTA. Это заставляет меня обойти проблему невозможности исключительно выбрать папку в HTML.

4 ответов


вам нужно запустить дождаться окончания процесса. Что-то вроде:

const DontWaitUntilFinished = false, ShowWindow = 1, DontShowWindow = 0, WaitUntilFinished = true
set oShell = WScript.CreateObject("WScript.Shell")
command = "cmd /c C:\windows\system32\wscript.exe <path>\myScript.vbs " & args
oShell.Run command, DontShowWindow, WaitUntilFinished

в самом скрипте запустите Excel так. При запуске отладки видно:

File = "c:\test\myfile.xls"
oShell.run """C:\Program Files\Microsoft Office\Office14\EXCEL.EXE"" " & File, 1, true

strComputer = "."
Set objWMIService = GetObject("winmgmts:\" & strComputer & "\root\cimv2:Win32_Process")
objWMIService.Create "notepad.exe", null, null, intProcessID
Set objWMIService = GetObject("winmgmts:\" & strComputer & "\root\cimv2")
Set colMonitoredProcesses = objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceDeletionEvent Within 1 Where TargetInstance ISA 'Win32_Process'")
Do Until i = 1
    Set objLatestProcess = colMonitoredProcesses.NextEvent
    If objLatestProcess.TargetInstance.ProcessID = intProcessID Then
        i = 1
    End If
Loop
Wscript.Echo "Notepad has been terminated."

Это может не конкретно ответить на ваш длинный вопрос 3 части, но этот поток старый, и я нашел это во время поиска сегодня. Вот один более короткий способ:" дождитесь завершения процесса."Если вы знаете название процесса, например" EXCEL.EXE-файл"

strProcess = "EXCEL.EXE"    
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\.\root\cimv2")
Set colProcesses = objWMIService.ExecQuery ("Select * from Win32_Process Where Name = '"& strProcess &"'")
Do While colProcesses.Count > 0
    Set colProcesses = objWMIService.ExecQuery ("Select * from Win32_Process Where Name = '"& strProcess &"'")
    Wscript.Sleep(1000) 'Sleep 1 second
   'msgbox colProcesses.count 'optional to show the loop works
Loop

кредит: http://crimsonshift.com/scripting-check-if-process-or-program-is-running-and-start-it/


наверное, что-то вроде этого? (непроверенные)

Sub Sample()
    Dim strWB4, strMyMacro
    strMyMacro = "Sheet1.my_macro_name"

    '
    '~~> Rest of Code
    '

    'loop through the folder and get the file names
    For Each Fil In FLD.Files
        Set x4WB = x1.Workbooks.Open(Fil)
        x4WB.Application.Visible = True

        x1.Run strMyMacro

        x4WB.Close

        Do Until IsWorkBookOpen(Fil) = False
            DoEvents
        Loop
    Next

    '
    '~~> Rest of Code
    '
End Sub

'~~> Function to check if the file is open
Function IsWorkBookOpen(FileName As String)
    Dim ff As Long, ErrNo As Long

    On Error Resume Next
    ff = FreeFile()
    Open FileName For Input Lock Read As #ff
    Close ff
    ErrNo = Err
    On Error GoTo 0

    Select Case ErrNo
    Case 0:    IsWorkBookOpen = False
    Case 70:   IsWorkBookOpen = True
    Case Else: Error ErrNo
    End Select
End Function