Тема: VBScript: запуск файлов ассоциированным приложением
Автор данной статьи - alexii.
Некоторые особенности методов DoIt, InvokeVerb, InvokeVerbEx, ShellExecute объекта автоматизации Shell.Application и метода Run объекта автоматизации WScript.Shell.
При опосредованном запуске приложений посредством методов DoIt, InvokeVerb, InvokeVerbEx, ShellExecute объекта автоматизации Shell.Application и метода Run объекта автоматизации WScript.Shell может возникнуть ситуация, что методы не будут работать как ожидается. Это может быть связано с тем, что скрипт завершает свою работу, прежде чем методы успевают отработать. Обычно подобное наблюдается, когда эти методы используются для опосредованного запуска «тяжёлых» приложений.
Демонстрация:
В папке C:\ShellExecute Demonstration находятся:
— текстовый файл Sample.txt;
— файлы Microsoft Word Sample.doc, Sample2.doc и Sample3.doc;
— файлы Microsoft Excel Sample.xls и Sample2.xls.
Option Explicit
Dim objShell
LogOut WScript.ScriptName & " started."
Set objShell = WScript.CreateObject("Shell.Application")
LogOut "Try run WinWord.exe by ShellExecute method"
objShell.ShellExecute "Sample.doc", "", "C:\ShellExecute Demonstration", "", 1
LogOut "Try run Notepad.exe by ShellExecute method"
objShell.ShellExecute "Sample.txt", "", "C:\ShellExecute Demonstration", "", 1
Set objShell = Nothing
LogOut WScript.ScriptName & " finished."
WScript.Quit 0
'=============================================================================
Function LogOut(varValue)
WScript.Echo CStr(Now()) & " : " & CStr(varValue)
End Function
'=============================================================================
В большинстве случаев строка скрипта
objShell.ShellExecute "Sample.txt", "", "C:\ShellExecute Demonstration", "", 1
отработает корректно и откроет приложение Notepad.exe c файлом C:\ShellExecute Demonstration\Sample.txt, а при исполнении строки
objShell.ShellExecute "Sample.doc", "", "C:\ShellExecute Demonstration", "", 1
может произойти:
— будет открыто приложение WinWord.exe с файлом C:\ShellExecute Demonstration\Sample.doc;
— будет открыто приложение WinWord.exe;
— будет запущен процесс WinWord.exe (окно приложения не появляется);
— ничего не произойдёт;
Если после вызова этих методов добавить в скрипт паузу некоторой длительности, то указанные методы отработают корректно (необходимое значение времени приостановки работы скрипта может зависеть от многих факторов, как-то: общего быстродействия компьютера, наличия антивируса и включённых эвристик проверки, размера открываемого файла, дефрагментации диска):
Option Explicit
Dim objShell
LogOut WScript.ScriptName & " started."
Set objShell = WScript.CreateObject("Shell.Application")
LogOut "Try run WinWord.exe by ShellExecute method"
objShell.ShellExecute "Sample.doc", "", "C:\ShellExecute Demonstration", "", 1
LogOut "Try run Notepad.exe by ShellExecute method"
objShell.ShellExecute "Sample.txt", "", "C:\ShellExecute Demonstration", "", 1
' Приостановка работы скрипта на 10 секунд
WScript.Sleep 10000
Set objShell = Nothing
LogOut WScript.ScriptName & " finished."
WScript.Quit 0
'=============================================================================
Function LogOut(varValue)
WScript.Echo CStr(Now()) & " : " & CStr(varValue)
End Function
'=============================================================================
Замечание: обратите внимание, что окно более «легкого» приложения Notepad.exe может появиться первым, несмотря на то, что опосредованно запускается вторым.
Подобным образом можно попробовать добиться корректной работы во всех перечисленных методах:
Option Explicit
Dim objShell
Dim objNameSpace
Dim objFolderItem
Dim objVerb
Dim objWshShell
LogOut WScript.ScriptName & " started."
Set objShell = WScript.CreateObject("Shell.Application")
LogOut "Try run WinWord.exe by ShellExecute method"
objShell.ShellExecute "Sample.doc", "", "C:\ShellExecute Demonstration", "", 1
Set objNameSpace = objShell.NameSpace("C:\ShellExecute Demonstration")
LogOut "Try run WinWord.exe by InvokeVerb method"
Set objFolderItem = objNameSpace.ParseName("Sample2.doc")
objFolderItem.InvokeVerb
LogOut "Try run WinWord.exe by InvokeVerbEx method"
Set objFolderItem = objNameSpace.ParseName("Sample3.doc")
objFolderItem.InvokeVerbEx
LogOut "Try run Excel.exe by DoIt method"
Set objFolderItem = objNameSpace.ParseName("Sample.xls")
For Each objVerb In objFolderItem.Verbs()
If objVerb.Name = "&Открыть" Then
objVerb.DoIt
Exit For
End If
Next
LogOut "Try run Excel.exe by Run method"
Set objWshShell = WScript.CreateObject("WScript.Shell")
objWshShell.Run """" & "C:\ShellExecute Demonstration\Sample2.xls" & """"
LogOut "Try run Notepad.exe by ShellExecute"
objShell.ShellExecute "Sample.txt", "", "C:\ShellExecute Demonstration", "", 1
' Приостановка работы скрипта на 20 секунд
WScript.Sleep 20000
Set objWshShell = Nothing
Set objVerb = Nothing
Set objFolderItem = Nothing
Set objNameSpace = Nothing
Set objShell = Nothing
LogOut WScript.ScriptName & " finished."
WScript.Quit 0
'=============================================================================
Function LogOut(varValue)
WScript.Echo CStr(Now()) & " : " & CStr(varValue)
End Function
'=============================================================================
Ещё одна особенность библиотеки SHELL32.dll проявляется в следующем примере:
Option Explicit
Dim objShell
Dim objNameSpace
Dim objFolderItem
Set objShell = WScript.CreateObject("Shell.Application")
Set objNameSpace = objShell.NameSpace("C:\ShellExecute Demonstration")
Set objFolderItem = objNameSpace.ParseName("Sample.txt")
objFolderItem.InvokeVerb "properties"
WScript.Sleep 5000
Set objFolderItem = Nothing
Set objNameSpace = Nothing
Set objShell = Nothing
WScript.Quit 0
Данный скрипт отображает окно свойств файла C:\ShellExecute Demonstration\Sample.txt (такое же, которое появится при выборе пункта Свойства контекстного меню файла в Проводнике). После того, как скрипт завершит свою работу, это окно будет автоматически закрыто. Если же убрать команду
WScript.Sleep 5000
это окно не отобразится вовсе.
Примечание от The gray Cardinal: похоже, вышеописанные методы DoIt, InvokeVerb, InvokeVerbEx, ShellExecute запускаются асинхронно. Если взять код, отвечающий за организацию паузы, и переставить его после очистки объектов, то ничего не изменится — всё по-прежнему будет работать. Поэтому, похоже, проблема заключается даже не в безвременном "R.I.P." объектов, а именно в завершении всего скрипта.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.