VBScript-как заставить программу ждать завершения процесса?
У меня есть проблема в VBScript, который я использую с макросом VBA/Excel и HTA. Проблема только в VBScript, у меня есть два других компонента, то есть макрос VBA и HTA front-end работают отлично. Но прежде чем я объясню проблему, я думаю, что для того, чтобы вы помогли мне, я должен помочь вам понять контекст VBScript.
Таким образом, в основном все компоненты (VBScript, VBA macro и HTA) являются частями инструмента, который я создаю для автоматизации некоторых ручных работ. Это в значительной степени идет как это:
A-HTA
~~~~~~~~~~~~
- пользователь выбирает некоторые файлы из HTA / GUI.
- в HTML HTA есть некоторый VBScript в тегах "SCRIPT", который передает пользователям 4 входных файла в качестве аргументов VBScript (выполняется WScript.exe-вы можете обратиться к примечанию #1 для ясности здесь)
- скрипт, назовем его myScript.vbs теперь обрабатывает 4 аргумента, 3 из которых являются конкретными файлами, а 4-Путь / папка расположение, в котором есть несколько файлов - (Также см. Примечание #2 для ясности)
B-myScript.vbs
~~~~~~~~~~~~
- мистический текст.vbs открывает первые 3 аргумента, которые являются файлами Excel. Один из них-это *.xlsm-файл, содержащий мой макрос VBA.
Мистический текст.затем 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)
...
Отсюда я создаю цикл, так что я могу последовательно открывать файлы в папке
а затем запустите мой макрос, т. е.
...
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.заявление о сне с 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
Comments