Метод Shell.Windows
Создает и возвращает объект ShellWindows . Этот объект представляет коллекцию всех открытых окон, принадлежащих оболочке .
Синтаксис
retVal = Shell.Windows()
Shell.Windows() As IDispatch
Параметры
Этот метод не имеет параметров.
Возвращаемое значение
Язык JScript
VB
Примеры
В следующем примере используется Windows для получения объекта ShellWindows и отображения количества элементов, содержащихся в нем. Для JScript, VBScript и Visual Basic отображается правильное использование.
Private Sub fnShellWindowsVB() Dim objShell As Shell Dim objShellWindows As ShellWindows Set objShell = New Shell Set objShellWindows = objShell.Windows If (Not objShellWindows Is Nothing) Then Debug.Print objShellWindows.Count End If Set objShellWindows = Nothing Set objShell = Nothing End Sub
Требования
Требование | Значение |
---|---|
Минимальная версия клиента | Windows 2000 Professional, Windows XP [только классические приложения] |
Минимальная версия сервера | Windows 2000 Server [только классические приложения] |
Заголовок | Shldisp.h |
IDL | Shldisp.idl |
DLL | Shell32.dll (версия 4.71 или более поздняя) |
Объект WScript.Shell метод Run — запуск внешних программ
Объектная модель Windows Script Host
Автор Coding На чтение 7 мин Просмотров 7.2к. Опубликовано 18.12.2014
Доброго времени суток всем читателям блога scriptcoding.ru. В этой статье мы подробно рассмотрим метод Run Wscript.Shell объекта. Данный метод служит для запуска внешних приложений из тела сценариев Windows Script Host.
Для начала мы рассмотрим теоретическую часть, а потом приступим к программированию.
Run (strCommand, [intWindowStyle], [bWaitOnReturn]) – данный метод служит для запуска другого приложения как в консольном режиме (командная строка), так и в оконном. При открытии исполняемого файла создается новый процесс. Ему передаются следующие параметры:
strCommand – данный параметр является обязательным, поскольку задает путь для файла или команды. Стоит учитывать, что если путь содержит пробелы, то его обязательно стоит заключать в двойные кавычки, иначе, возникнет ошибка « The system cannot find the file specified » – система не может найти указанный файл. Также полезно, использовать переменные окружения в пути к приложению, это экономит время.
intWindowStyle – является необязательным, и задает стиль окна. Параметр может принимать целые значения от 0 до 10. Согласно документации, в языке vbscript можно использовать именованные константы, но, они не всегда дают ожидаемый результат, и так как эти значения между собой повторяются, я упомянул лишь три:
- 0 – скрывает окно, будет виден только процесс в диспетчере задач.
- 1 – нормальный режим
- 2 – свернутый вид
- 3 – развернутый вид
bWaitOnReturn – может принимать true – сценарий будет ожидать завершения работы запущенного приложения, и только потом перейдет к выполнению следующей строчки кода, false – будет продолжатся выполнение сценария независимо от того, завершилась работа запущенного приложения или нет. Также следует учесть, что если установлено true, то метод вернет код выхода вызванного приложения, если установлено false – всегда будет возвращаться ноль.
Хорошо, теперь настало время заняться программирование. Для начала напишем программный код на языке VBScript:
'******************************************************* ' метод wscript shell run ' Запуск бл0кн0та и калькулятора ' wshshell_run.vbs '******************************************************* Option Explicit dim path, WshShell ' задаем путь к системной папке path = "%WINDIR%\System32\" ' Создаем ссылку на объект WscriptShell set WshShell = WScript.CreateObject("Wscript.Shell") ' Открываем notepad (Wshshell Run) WshShell.Run path & "notepad.exe", ,true MsgBox "Текстовый редактор завершил работу. " & vbCrLf & "Запускаем калькулятор" ' Открываем calc WshShell.Run path & "calc.exe",2,false MsgBox "Этот текст выводится сразу"
‘*******************************************************’ метод wscript shell run’ Запуск бл0кн0та и калькулятора’ wshshell_run.vbs’*******************************************************Option Explicitdim path, WshShell’ задаем путь к системной папкеpath = «%WINDIR%System32″‘ Создаем ссылку на объект WscriptShellset WshShell = WScript.CreateObject(«Wscript.Shell»)’ Открываем notepad (Wshshell Run)WshShell.Run path & «notepad.exe», ,trueMsgBox «Текстовый редактор завершил работу. » & vbCrLf & «Запускаем калькулятор»‘ Открываем calcWshShell.Run path & «calc.exe»,2,falseMsgBox «Этот текст выводится сразу»
Давайте проанализируем логику работы данного сценария. Переменная path хранит путь к папке System32, так как в ней у нас лежат исполняемые файлы notepad и calc. Переменная окружения « %WINDIR% » позволяет сократить строки кода и не писать « C:\Windows «. WshShell содержит ссылку на экземпляр объекта Wscript.Shell, видим, чтобы создать саму ссылку, мы перед переменной прописали ключевое слово set, после чего идет вызов метода CreateObject класса WScript, подробней о работе с объектами читайте «Урок 8 по VBScript: Объекты и классы» и «Урок 4 по JScript: Создание собственных объектов«. Далее мы запускаем блокнот с помощью метода Run Wscript Shell класса, через переменную WshShell. Для программы notepad мы третий параметр команды Run поставили в true, поэтому, исполняемый файл calc запустится только после закрытия приложения блокнот, плюс, перед этим появится информационное сообщение.
Хорошо, теперь давайте посмотрим на аналогичный пример, но написанный уже на языке jscript.
//******************************************************* // метод wscript shell run // Запуск бл0кн0та и калькулятора // wshshell_run.js //******************************************************* var path, WshShell; // задаем путь к системной папке path = "%WINDIR%\\System32\\"; // Создаем ссылку на WscriptShell WshShell = WScript.CreateObject("Wscript.Shell"); // Запускаем notepad (Wshshell Run) WshShell.Run (path + "notepad.exe",1,true); WScript.Echo ("Текстовый редактор завершил работу. " + "\n" + "Запускаем калькулятор"); // Запускаем calc WshShell.Run (path + "calc.exe",2,false); WScript.Echo ("Этот текст выводится сразу");
//*******************************************************// метод wscript shell run// Запуск бл0кн0та и калькулятора// wshshell_run.js//*******************************************************var path, WshShell;// задаем путь к системной папкеpath = «%WINDIR%\System32\»;// Создаем ссылку на WscriptShellWshShell = WScript.CreateObject(«Wscript.Shell»);// Запускаем notepad (Wshshell Run)WshShell.Run (path + «notepad.exe»,1,true);WScript.Echo («Текстовый редактор завершил работу. » + «n» + «Запускаем калькулятор»);// Запускаем calcWshShell.Run (path + «calc.exe»,2,false);WScript.Echo («Этот текст выводится сразу»);
В данном примере, мы видим, что для команды Run мы прописали второй параметр (1 – нормальный режим), если этого не сделать, то произойдет ошибка, язык jscript не дает нам возможности пропустить параметр. Также видим, что тут не нужно использовать дополнительное ключевое слово типа set.
WScript Shell Run
Хорошо, теперь давайте посмотрим на еще один пример на языке vbscript.
'******************************************************* ' метод wscript run ' Запуск бл0кн0та и передача ему текста ' wscript_run.vbs '******************************************************* Option Explicit dim WshShell ' Создаем ссылку на WscriptShell set WshShell = WScript.CreateObject("Wscript.Shell") ' Открываем текстовый редактор и вставляем в него содержимое сценария WshShell.Run "notepad.exe " & WScript.ScriptFullName,1,true MsgBox "Мы открывали текстовый редактор"
‘*******************************************************’ метод wscript run’ Запуск бл0кн0та и передача ему текста’ wscript_run.vbs’*******************************************************Option Explicitdim WshShell’ Создаем ссылку на WscriptShellset WshShell = WScript.CreateObject(«Wscript.Shell»)’ Открываем текстовый редактор и вставляем в него содержимое сценарияWshShell.Run «notepad.exe » & WScript.ScriptFullName,1,trueMsgBox «Мы открывали текстовый редактор»
В этом примере мы также запустили приложение notepad, но, не прописывали путь к нему. Дело в том, что команда Run объекта Wscript.Shell работает как команда « Windows Пуск/Выполнить «, и при запуске приложения, сперва идет его поиск в переменных средах Windows, в которые, и входит папка System32 . Также видим, что мы передали программе содержимое нашего сценария (строка WScript.ScriptFullName), фактически, скопировали в него весть текст скрипта.
Ну и напоследок, аналогичный пример, но уже на языке jscript:
//******************************************************* // метод wscript run // Запуск бл0кн0та ему текста // wscript_run.js //******************************************************* var WshShell; // Создаем ссылку на WscriptShell WshShell = WScript.CreateObject("Wscript.Shell"); // Открываем текстовый редактор и вставляем в него содержимое сценария WshShell.Run ("notepad.exe " + WScript.ScriptFullName,1,true); WScript.Echo ("Это был запуск текстового редактора");
//*******************************************************// метод wscript run// Запуск бл0кн0та ему текста// wscript_run.js//*******************************************************var WshShell;// Создаем ссылку на WscriptShellWshShell = WScript.CreateObject(«Wscript.Shell»);// Открываем текстовый редактор и вставляем в него содержимое сценарияWshShell.Run («notepad.exe » + WScript.ScriptFullName,1,true);WScript.Echo («Это был запуск текстового редактора»);
И так, давайте все подытожим… В этой статье мы разобрали метод Run класса Wscript Shell, который позволяет запускать заданное приложение, и передавать ему нужные параметры, так, мы можем открыть текстовый редактор и вставить в него нужный текст. Аналогично, можно использовать и метод Exec, который тоже позволяет запускать исполняемый файл, но в отличии от метода Run, он позволяет контролировать работу исполняемого файла.
Запуск Wscript.Shell и Shell.Application. Заметки
Общих обзоров и материалов на эту тему уже достаточно, данная заметка не претендует на полноценную публикацию или исследование нюансов. Рассматривается только ОС Windows и только с точки зрения разработчика 1С, без подробностей системного администрирования и погружения в API винды. Переход по навигационным ссылкам (открытие страниц, запуск программ по протоколам) и открытие/запуск приложений по ассоциированным файлам не рассматриваем. В общем случае разработчику доступны два командных процессора, cmd или powershell. Это именно исполнители команд, передающие далее ядру ОС более низкоуровневые команды; они доступны из консолей, пункта меню «Выполнить», они лежат в основе многих действий графических оболочек и системных менеджеров. При этом, cmd не имеет «надстройки», и обращение к ней это всегда консольная команда. А вот powershell предоставляет оболочку над утилитой, что упрощает некоторые действия, но создаёт путаницу между собственно процессором и его «управляющим» объектом в памяти некоего процесса. Причём, эта оболочка позволяет вызвать выполнение cmd. Сложно сказать, в каких терминологических отношениях, например, находятся API-функции и процессоры, поэтому фиксируем лишь практически важные, прикладные моменты. Важно не путать, что мы запускаем (какой процессор) и чем запускаем (какая оболочка). Под оболочкой рассматриваем СОМ-объект, созданный динамически в ходе исполнения кода на языке 1С, безотносительно, на сервере 1С это или на клиенте. Для запуска разработчику доступны две оболочки, WScript.Shell и Shell.Application. Суть одинакова: создаётся их объект, ведётся работа с его методами и свойствами, а суть — в исполнении командной строки, команды, обычно с параметрами. В общем случае командой может быть директива ОС, собственно команда, запуск пакетного файла (скрипта), запуск исполняемого файла, открытие файла по ассоциации ОС итд. В общем случае всё это можно звать запускаемым сценарием. Запуск может ждать завершения, т.е. остановить процесс-инициатор до момента окончания/прерывания/вылета запущенного процесса, либо продолжить процесс-инициатор и взаимодействовать с запущенным в реальном времени. Называть ли это асинхронностью или многопоточностью — не столь важно, но с помощью взаимодействия нескольких запущенных процессов и их «родителя» можно добиться параллельности некоторых действий. Правильнее вообще говорить не столько об ожидании завершения, сколько об управляемости запущенного. В обоих случаях запущенный что-то получает на вход, что-то отдаёт на выход (и как код возврата, и, если предусмотрел разработчик, как подробные выходные данные), что-то сообщает при ошибке. Всё это — общеизвестные потоки StdIn, StdOut, StdErr. Разумеется, не считая собственных фишек запускаемой команды, например, чтения из где-то лежащих файлов, записи в реестр итд. Поток можно читать поэтапно, целиком, направлять в переменную или файл, и всё это доступно либо на уровне файловых команд, либо через свойства и методы оболочек. Можно напрямую прописывать вывод результатов исполнения в файл (> и >>, т.е. полная перезапись и дописывание соответственно), учитывая доступ к местоположению такого файла. WScript.Shell Каждый экземпляр объекта WScript автоматически создаётся сервером сценариев (CScript.exe или WScript.exe) в момент вызова конструктора. Регистрация в СОМ+ и DCOM не требуется. Создание:
Оболочка = Новый COMОбъект(«WScript.Shell»); // во времена 8.2 это не всегда работало, требовалось «подружить» 1С и WSH
О свойствах оболочки
Некоторые полезные свойства:
* Разумно проверять текущее значение Оболочка.CurrentDirectory — это может быть совсем не та папка, что казалось бы. Изначально — в большинстве случаев — та, откуда был запущен скрипт. Важно в смысле доступа для последующих действий.
* Окружение можно смотреть из свойства Оболочка.Environment, содержащего коллекцию с значениями переменных. Можно уточнить, какой тип переменных нужен: Environment(СтроковоеИмяТипа)
System — системные переменные окружения (именно её возвращает по умолчанию)
User — пользовательские переменные окружения
Volatile — временные переменные окружения
Process — переменные окружения текущего командного окна
В разных ОС список конкретных переменных различается. Из свойств объекта Оболочка можно выяснить путь, имя, версию сервера сценариев, что полезно при расследовании нетипичного поведения.
В некоторых случаях в передаваемой командной строке надёжнее писать путь вызова в формате 8х3, т.е. «C:\Progra~1\» итд. По завершении работы с Оболочка её надо принудительно приравнять Неопределено. Если объект был создан на управляемой форме, то, за исключением общеизвестного «удержания», контекст и занимаемая память по закрытии формы будут сброшены, а вот если создан из общего модуля, и сложился ещё ряд факторов, то может остаться в памяти, в т.ч. по завершении создавшего сеанса. Оболочка, в свою очередь, позволяет создавать процессы ОС, как объекты типа WshScriptExec (некоторые источники утверждают, что может потребоваться доступ ко всем зарегистрированным классам, на практике не сталкивался). Опять же, можно запускать консольно: cscript.exe ПутьВКавычкахКФайлуСценария (запуск сценариев пакетно). Такой подход позволяет указать, какой сервер сценариев применять (CScript.exe или используемый по умолчанию WScript.exe), можно подавить вывод диалогов и сообщений сценария.
С возможностью управления Запуск с порождением отдельного дочернего управляемого процесса, без ожидания завершения. Процесс = Оболочка.Exec(СтрокаЗапуска);
О свойствах процесса
Некоторые свойства:
* ProcessID – идентификатор процесса, позволяет манипулировать им в различных методах Оболочки. В диспетчере задач виден на серверных ОС.
* Status – число: если процесс выполняется, то 0, если прекратил свою работу то 1 (неважно, по какой причине прекратил). * Arguments содержит коллекцию, позволяющую обращаться к именным и безымянным параметрам скрипта по отдельности, и многое другое. Например:
// Условия, при которых эта коллекция доступна после завершения запущенного процесса, зависят от вида сервера сценариев. Для каждого Аргумент Из Оболочка.Arguments Сообщить(Аргумент); КонецЦикла;
* Interactive — можно разрешать/запрещать интерфейсное взаимодействие с пользователем, что важно на клиенте. Также можно проверять с его помощью, не был ли скрипт запущен в пакетном режиме (параметр «//B» сервера сценариев). * ExitCode возвращает результат (именно и только для уже завершённого), обычно это некое число. Также в документациях упоминаются расширенные свойства:
* OutputEncoding — строковое имя кодировки потоков, но, всегда ли оно есть у WshScriptExec, в документациях не нашёл;
* HasExited — булево; завершён ли (опять же, без детальной диагностики, по какой причине). Во многих примерах фигурирует свойство, которое крайне нестабильно работает в 1С: Оболочка.Timeout, якобы позволяющее до запуска указать, через какое заданное в секундах время остановить процесс. Не рекомендую с ним связываться, т.к. по аналогии с обработчиком ожидания, таймер, похоже, тикает лишь при некоторых условиях, и тупит при большой нагрузке. По умолчанию время исполнения сценария не ограничено.
Входной, выходной, ошибочный потоки: StdIn, StdOut, StdErr — это тоже свойства, возвращающие актуальные на момент обращения к ним потоки, они имеют тип объект «TextStream», соответствующий стандартному потоку. Доступны, если скрипт запущен с помощью CScript.exe.
ВходнойПоток = Оболочка.StdIn.ReadLine() или ReadAll(), или Read(КолвоСимволов).
Выходной поток StdOut и поток ошибок StdErr аналогично. Примечания по потокам:
* Некоторые приложения пишут вывод прямо в консоль, а не в стандартный поток, поэтому читать его, а равно и перенаправлять куда-то, бесполезно.
* Ввод и вывод буферизуются, поэтому важно не забывать про свойство Поток.AtEndOfStream; например, известны случаи, когда из StdOut читается сразу всё-всё, или просто больше, чем буферизовано, то процесс 1С может тихо рухнуть (наблюдалось на 8.3.18.1289), а если читается строка, после которой программа ожидает ввод текста, то управление в запустивший процесс 1С никогда не вернётся и 1С повиснет. Особенно это касается фоновых заданий — при неаккуратной работе с потоками очень глючат. Процесс, запущенный Exec, разумно мониторить в цикле с задержкой, и при необходимости насильственно прерывать. Для этого используют: * Процесс.Terminate(); // показал себя как наиболее надёжный, но, если процесс уже завершился (например, рухнул по ошибке), вызов этого метода тоже вызовет ошибку; метод позволяет завершить дочерний процесс. Процессу будет послана команда WM_CLOSE, если это не сработает, то процесс будет завершен принудительно; * Процесс.Quit(КодВозвратаКакОшибки) — необязательный числовой код возврата приложения // код возврата будет не в потоке выхода и не в потоке ошибок, а именно в ExitCode; метод поддерживается не всеми серверами. Важно учитывать, что на 64-х битном сервере 1С (Именно 1С, не ОС) вспомогательный объект, например, «Процесс», не создается согласно политикам безопасности. Не все 32-х битные COM-ы могут быть вызваны 64-х битным приложением — например, MSScriptControl не может. И вообще приложение может быть скомпилировать в несовместимой разрядности, и сервер сценариев не сможет создать экземпляр объекта процесса такого приложения. Метод позволяет контролировать ход работы запущенного процесса, и запущенный сценарий является дочерним для запускающего, ему присущи те же переменные среды Windows, что и у процесса-родителя, и те же ограничения доступа. Использование метода разумно для консольных приложений, которые выполняются в консольном окне, особенно с диалогами запросов пользователю. Видимость диалога определяется запуском на клиенте 1С и совокупностью свойств сервера сценариев. Метод работает более адекватно и прозрачно при возможных ограничениях UAC. Концепция: запустили и управляем сами: можем подождать (Sleep), можем сразу опросить, можем прервать из 1С.
Без возможности управления Запуск внешних приложений с ожиданием завершения. КодВозврата = Оболочка.Run(СтрокаЗапуска, СостояниеОкна, ЖдатьЗавершения); * СтрокаЗапуска — строка сценария; если содержит пробелы, то обязательно заключать её в двойные кавычки, иначе выдаст «The system cannot find the file specified», и настоятельно рекомендуется использовать переменные окружения в пути к приложению. Для Exec подобные требования менее часты и менее жёстки.
* СостояниеОкна — число (интересно разве что на клиенте), и обобщая VBScript, они таковы: 0 – скрывает окно, будет виден только процесс в диспетчере задач. 1 – нормальный режим 2 – свернутый вид 3 – развернутый вид;
* ЖдатьЗавершения — булево, остановить процесс-инициатор или продолжать. Если установлено Истина, то метод вернет числовой код возврата вызванного приложения, если установлено Ложь – всегда будет возвращаться ноль. Никаких свойств или объектов не предусмотрено. Метод работает строго аналогично команде ОС Windows «Пуск/Выполнить», и при запуске приложения сперва идет его поиск в переменных среды, поэтому имена наиболее употребительных приложений можно указывать без пути. Метод не позволяет контролировать ход работы запущенного процесса, и дочерним для запускающего запущенный сценарий не является, а идёт как независимый. При наличии неочевидных UAC работа метода превращается в чёрный ящик. Диалоги могут быть видны, но «живут своей жизнью», а разумнее всего применять метод к приложениям, не выводящим никакие диалоги. Замечено, что в некоторых скриптах своеобразно игнорирует «@echo off», выводя пустое окно консоли на пару секунд. Концепция: запустили и ждём, пока сама ОС не разберётся и не вернёт управление 1С.
Shell.Application Как оболочка, по сути это программно-скриптовый способ обращения к объекту, представляющему диспетчер запускаемых задач, в графическом интерфейсе — банальный Windows Explorer (проводник). Работа с такой оболочкой тесно связана с возможностями и доступностью технологии OLE/COM-АctiveX, и вообще в значительной степени это просто Automation-сервер. Более чувствительна к свойствам объекта приложения, с которым имеет дело. Задействуются системные файлы проводника и Shell32.dll (чьи версии очень разные в зависимости от сборок; так, например, большинство современных возможностей пошли с PowerShell 4.0 от Win 8.1, и даже в MSDN открыто пишут, что не все объекты, свойства и методы гарантированно работают на все версиях Windows, а в качестве средства победить баг в первую очередь советуют ставить обновления для. MSIE. Вообще PowerShell как оболочка — способ менее прозрачный, менее управляемый, более зависимый от контекста среды, но имеет ряд достоинств. Технически, shell-команды могут транслироваться в имена для ActiveX-элементов, например, описанных как ShellFolder в реестре (так, «shell:Downloads» это папка загрузок текущего юзера). Если АctiveX не имеет имени (а оно есть не всегда), можно обратиться по CLSID (так, «shell. » — это команда свернуть все окна).
С точки зрения разрешений и прав доступа, поведение PowerShell определяется и управляется, по умолчанию, профилем пользователя, под которым выполнялся запуск. Соответственно, на сервере 1С это пользователь ОС, под которым запущена служба (например, USR1CV8). Пользователи ИБ и БД, напомню, описаны на ИТС, обсуждались тут: https://forum.infostart.ru/forum9/topic224824/ Для запуска команд применяют метод ShellExecute и его расширенный вариант, начиная с Vista, ShellExecuteEx. Оба метода позволяют чётко разделить исполняемую команду и параметры к ней (не на уровне положения в командной строке или сценарии, а на этапе вызова). При вызове этих команд вызывается СОМ-консольно основная утилита-процессор: powershell , т.е. по сути аналог start-process, а уж что ей передано, определяет разработчик. Повторюсь, это может быть команда, директива, имя файла скрипта; всё это с указанием командного процессора и, главное, с возможностью обойтись без ввода пароля и подтверждения UAC, что особенно ценно при исполнении на сервере, да ещё в фоновом задании. Можно применять напрямую процессор cmd, так, «powershell -Command» идёт применительно к нему. Создание: Оболочка = Новый COMОбъект(«Shell.Application»); // если проблема с совместимостью, разрядностью или правами, то уже это действие завершится ошибкой По завершении работы с Оболочка её желательно принудительно приравнять Неопределено, но по завершении сеанса/процесса-инициатора, т.е. 1С, также будет удалена. Кто знает примеры с зависанием и тем более утечкой памяти — пожалуйста, поделитесь. ShellExecute КодВозврата = Оболочка.ShellExecute(КомандныйПроцессор, АргументыДляДействия, КаталогВыполнения, ДействиеГлагол, СостояниеОкна); // все параметры, кроме первого, необязательны * КомандныйПроцессор — например, «cmd»; * АргументыДляДействия — описание сценария, например, «/c «»» + ИмяФайлаИлиКоманда + «»»»; * КаталогВыполнения — по умолчанию используется текущий каталог того сервера и того процесса, который инициирует запуск; * ДействиеГлагол — см.ниже. * Состояние окна интересно только на клиенте, это рекомендуемое состояние окна при выполнении, многие приложения это игнорируют, нотация аналогична вышеприведённой по vbs); Результат метода, т.е. КодВозврата — именно возвращаемое запущенным процессом значение, а не какой-либо из связанных с ним потоков. Метод позволяет использовать «действия», «глаголы» (Verbs), детализирующие выполняемое действие. Есть глаголы, применимые лишь к конкретным приложениям и не во всех случаях: «edit» (запуск редактора), «find» (поиск файла), «print» (печать файла), «properties» (получение свойств файла). Глагол по умолчанию — open. Для разработчика 1С представляет интерес глагол «Open» — запуск приложения, а если это не исполняемый файл, то ассоциированного с ним. В большинстве документаций нет глагола, определяющего запуск от имени администратора, однако он есть и называется «runas», и тут есть нюансы. Отсутствие запроса подтверждения UAC не эквивалентно эскалации привилегий текущего пользователя, под которым выполняется запуск, или привилегий конкретного процесса — обычно речь идёт о запуске этим процессом другого, уже с административными полномочиями и наследованием переменных контекста. Для этого в рамках командной строки применяется ключ «-verb runas» (регистр букв не важен), а в рассматриваемом методе, например, ShellExecute(«cmd», «/c «»» + Команда + «»»», , «runas», 0); Такой запуск имеет свои особенности: вместе с «-Verb RunAs» нельзя использовать вывод в файл через -RedirectStandardError и -RedirectStandardOutput, нельзя указывать -Wait и -NoNewWindow.
Пример запуска самой оболочки из-под себя с повышением прав: powershell «start-process powershell -verb runas». Надеюсь, очевидно, что PowerShell RunAs небезопасна, т.к. SaveCred добавляет удостоверение администратора и пароль в кэш учетных данных, и этот кэш, в принципе, можно перехватить. При этом, в ряде случаев поведение Windows Credential Manager может не удовлетворять требованиям безопасности, и тогда никакое повышение не сработает, и далеко не всегда это ловится кодом возврата, возможно, придётся смотреть журнал событий винды. За возможность запуска программ от имени другого пользователя в Windows отвечает служба вторичного входа в систему (Secondary Log-on). Если эта служба остановлена, все описанные методы с RunAs работать не будут (проверить, запущена ли служба, можно командой PowerShell вида «Get-Service seclogon»).
Другие способы, связанные с RunAs
Есть способ запуска из объекта FolderItems или FolderItem методом InvokeVerb, и InvokeVerbEx с конкретизацией параметров:
objFolderItem.InvokeVerbEx(«open», «c:\my.bat») — т.е. над одной папкой или каждой из коллекции выполнить указанное действие.
Это именно действие ОС (если задано для коллекции, в т.ч. по вложенным папкам, то работает не рекурсивно). Допустимые возможные действия для объекта можно получить из его свойства-коллекции Verbs. На практике использования из 1С не встречал. Есть способ запуска с применением «\System32\runas.exe» — консольной утилиты, которая априорно выполняет указанную команду/директиву/скрипт с повышением прав. В части логина и пароля администратора утилита также взаимодействует с Windows Credential Manager — требует либо явного указания имени пользователя и пароля, либо использования saved credentials. Тут это уже не глагол, как уточняющий аргумент в методе, а просто отдельная программа.
Например, runas /user:ИмяДомена\ЛогинАдмина «C:\Windows\notepad.exe» — это запуск блокнота под админом в домене.
Если надо запустить программу от имени доменного пользователя с компьютера, который не добавлен в домен AD, или в бездоменной сети, то команда будет такая:
runas /netonly /user:contoso\ИмяЮзера cmd.exe — и это при условии, что в сетевых настройках ПК указан DNS-сервер, способный корректно интерпретировать обращение; ну или указывать IP.
Если для запуска программы от другого пользователя не требуется загружать его профиль, можно указать параметр /noprofile — запуск станет гораздо быстрее, но если запускаемый процесс опирается на данные, хранящиеся в профиле того пользователя, то его работа будет некорректна или невозможна. Встречал в интеграции 1С с драйверами внешних устройств.
Примечания
1. По некоторым утверждениям, PowerShell может зависать при обработке входного потока, если не указать «-InputFormat none», когда была передана явно прописанная команда «-Command «%cmd%»»; для нас это может представлять интерес при передаче, например, параметра запуска при консольном старте 1С.
2. По некоторым утверждениям, ShellExecute лучше, чем все методы WScript.Shell, для запуска ярлыков, т.е. зарегенных приложений по lnk, по скорости запуска. Не проверял, но советую взять на заметку.
3. Если рассматривать глагол как дочерний объект от построенного объекта запуска, то у него есть свойство Name и метод DoIt, однако это эквивалентно передаче в скрипте или команде, и для нужд запуска без приостановок и принудительных возобновлений хода процесса интереса не представляет.
4. В ряде случаев при недостатке прав и использовании runas может потребоваться однократная правка реестра для запускаемого приложения, иначе будет выдано сообщение в духе «выполнение сценариев отключено в этой системе.», т.к. самостоятельно перезапустить сценарий уже как отдельный процесс под админом 1С может и не суметь; иногда лучше такое организовать в bat-файл.
5. В ряде случаев может потребоваться отслеживать по SID, с каким процессом имеем дело — исходным или уже админским, если нужна детальная диагностика (например, по потребляемым ресурсам).
6. Методы запуска не следует путать с методом Оболочка.FileRun(), который просто выдаёт консольное окно, ждущее команды пользователя, аналог «Выполнить», но ничего само не делает.
Общие моменты * Всегда учитывать, что VBScript разрешает пропускать необязательные параметры методов, а JScript нет! Особенно при заимствовании кода и копи-пасте с примеров в сети))) * Ключевое значение имеет кодировка — и путей, передаваемых как параметры, и команд, и строк в скриптах, и потоков. Есть кодировка, указанная напрямую в файле скрипта (chcp), и есть, в которой записан файл скрипта и читаются файлы потоков, их нельзя путать и следует проверять/настраивать отдельно. Не стоит уповать на 1С-ный Юникод или системные настройки по умолчанию. Кавычку, например, для верности лучше задавать напрямую как Символ(34). * Следует быть аккуратнее с расшаренными ресурсами, и с теми, запись в которые виртуализируется. У виртуальных дисков в консольных запусках порой запаздывает отклик ОС по доступу, в т.ч.отказ. * Если прав по UAC недостаточно, то при запуске на клиенте может вылезти consent.exe с диалогом запроса подтверждения, а на сервере просто втихую не запустится. До потоков вывода и ошибок. До каких-то объектных действий. В таких случаях команду лучше обёртывать запускаемым файлом-скриптом (как делает БСП), а на сервере только смотреть журнал ОС насчёт ошибок, смотреть настройки безопасности IE (при нужде добавлять server-ivc в доверенную зону, с которой разрешён запуск исполняемых). * Создание сом-объекта, естественно, оборачиваем в попытку-исключение и, естественно, нам доступно только позднее связывание, т.к. такие вещи как Active-Х и тем более OLE статично в объекты 1С не впихнуть. И не забываем про деструктор и уборку мусора за собой. * Если надо содержимое консольного окна успеть посмотреть, а оно закрывается, используем (например, последней командой в скрипте) команду PAUSE, но тогда помним про особенности чтения потока вывода. По мнению «1С» На ИТС сравнительно мало конкретики, посвящённой особенностям работы СОМ-объектов с оболочками ОС, и она разрозненна. Процитирую наиболее полезное: «При запуске внешней программы из кода требуется составлять строку запуска таким образом, чтобы она собиралась только из проверенных частей. если одна из частей, из которых собирается строка запуска, содержит данные, полученные из базы данных, из поля ввода на форме или прочитаны из хранилища настроек, то перед запуском программы требуется проверить, являются ли запуск безопасным. Безопасными считаются такие строковые данные, которые не содержат в себе следующие символы: «$», «`», «|», «||» «;», «&», «&&». Данное требование распространяется на все способы запуска программ.» С одной стороны, выглядит разумно; с другой — наличие в списке символа «;» делает небезопасным, например, запуск другой 1С по строке соединения /IBConnectionString, «благодаря» чему воспользоваться БСП для таких действий затруднительно.
Как сделано в БСП
В современной БСП принята концепция «оборачивания» любой команды в скрипт, куда в любом случае дописывается указание кодировки. Т.е. даже если вы скомпоновали свой скрипт и передаёте путь к нему, учтите — он будет вызван из другого скрипта. Разработчику доступны методы:
ФайловаяСистемаКлиент.ЗапуститьПрограмму (в клиентском коде);
ФайловаяСистема.ЗапуститьПрограмму (в серверном коде) Как работают оба метода:
Если нужно получение потока вывода и/или потока ошибок, то объявляются временные файлы stdout.tmp и stderr.tmp, и к самой строке команды дописывается перенаправление потока в них (перезаписью). Создаётся отдельный текстовый документ с именем run.bat, и в него пишется следующее:
"@echo off" // иногда дописывает ByteOrderMark в начало, поэтому команда далеко не всегда отрабатывает "chcp 437" // т.е. OEM; или 866, т.е. CP866; или 65001, т.е. UTF8; итд; //Если указан принудительно текущий каталог, то дописывает "cd /D НужныйКаталог" // причём он обязательно забирается в кавычки, даже если они уже были, что тоже может оказаться проблемой; "cmd /S /C СтрокаКоманды" // собственно строка команды, как новый экземпляр командного процессора, выполнение с завершением работы (ключ /C), и обязательно забирается в кавычки, даже если они уже были; //возможно несколько команд (это в связке с наличием кавычек даёт ключ /S), через разделитель && //что интересно, режима отключения вывода команд на экран, т.е. /Q, не передаётся
Файл run.bat и на сервере, и на клиенте сохраняется просто как временный файл. А дальше.
// Для файловых ИБ запускают: Оболочка = Новый COMОбъект("Shell.Application"); КодВозврата = Оболочка.Run(ПутьИмяБатФайла, 0, ДождатьсяЗавершения); // Для серверных ИБ запускают: ЗапуститьПриложение(ПутьИмяБатФайла, , ДождатьсяЗавершения, КодВозврата);
Если указана необходимость дождаться завершения, то файл удаляется принудительно после запуска, не дожидаясь конца сеанса. Если ждать завершения не надо, тут может возникнуть потенциальная утечка памяти, т.к. сеанс 1С, натыкаясь на невозможность удалить порождённый им временный файл, просто игнорирует его и закрывается без лишних жалоб.
При необходимости (если дождались завершения), читаются файлы потоков (с помощью ЧтениеТекста, сразу целиком и в той же кодировке, что скрипт), и также принудительно удаляются. Опять-таки, если завершения не ждать, то и работать с файлами потоков разработчику придётся самостоятельно. На практике подобный подход, обёртывание в bat, показал меньшую стабильность при работе в фоновых заданиях, чем прямое указание команды. Ну и, если дело на клиенте, и фокус «уплыл», и пользователь случайно нажал Ctrl+Break, то ведь оно и остановиться может.
P.S. Всё вышеизложенное — так или иначе — баян и повтор. После блестящей статьи Ю.Пермитина вообще мало смысла освещать эту тему. Поэтому — просто заметка, скорее даже для себя. Аккордеон-антисклерозник. P.P.S. Тухлые помидоры приветствуются, но, по возможности, конструктивные.
Wscript shell что это
Если в обработке выполнить:
WshShell = Новый COMОбъект(«WScript.Shell»);
WshShell.Run(«C:\test.cmd», 1, False);
то появляется окно с программой, а если это же выполнить в фоновом задании то окно не появляется, почему так и что делать?
а фоновому заданию окно зачем?
и второй вопрос. ЗапуститьПриложение() или КомандаСистемы() не предлагать?
ошибки есть при выполнении фонового задания ?
(0) Заменить 1 на 0
WshShell.Run(«C:\test.cmd», 0, False);
(1) надо)
(2) нужно попробывать
(3) нет
(4) не в этом дело
ну дык cmd полюбасы будет в чёрном окошке выполняться.
хотя, есть утилитки всякий для сокрытия, типа cmdow
фоновое задание выполняется на сервере
(6) в (1) был намёк на (8)
Самое главное, что окно появляется — только на рабочем столе сервиса, под которым работает сервер — и, если в сценарии ошибка, то это «чудное» окно просто будет занимать память, пока сервер не перезапустят (или вручную не убьют процесс).
Глупец, лишенный способности посмеяться над собой вместе с другими, не сможет долго выносить программирование. Фредерик Брукс-младший