Как вызвать cmd из кода 1С: ЗапуститьПриложение, WScript.Shell, bat-файлы
Содержание
Вызвать командную строку из 1С можно тремя путями: встроенным методом ЗапуститьПриложение, через COM-объект WScript.Shell или запуском заранее подготовленного bat-файла. Самый короткий вариант выглядит так: ЗапуститьПриложение("cmd.exe /c dir C:\Temp > C:\Temp\list.txt", , Истина);. Третий параметр Истина заставляет 1С дождаться завершения команды.
Проблемы начинаются потом. Код работает у вас в тонком клиенте и молчит в веб-клиенте. На сервере команда уходит не на тот компьютер. Кириллица в выводе превращается в «кракозябры», а антивирус режет bat-файл. Ниже разобраны способы запуска, передача параметров, чтение результата и ограничения, о которые спотыкаются чаще всего.
Где запуск cmd вообще возможен
Команда выполняется на той машине, где работает код. Это определяет всё остальное.
| Контекст | Где исполняется cmd | Что учесть |
|---|---|---|
| Тонкий и толстый клиент | Компьютер пользователя | Права текущего пользователя Windows |
| Веб-клиент | Не поддерживается | Запуск программ ОС недоступен |
| Сервер 1С (клиент-серверный вариант) | Сервер, где работает rphost | Права пользователя, под которым запущена служба сервера 1С |
| Файловая база, серверный вызов | Компьютер пользователя | Сервер и клиент совпадают |
| Внешнее соединение, COM | Машина, где создан COM-объект | Зависит от процесса, который вызвал код |
Главное правило: код, исполняемый на сервере, никогда не откроет окно у пользователя. Он запускает процесс на сервере, и пользователь его не увидит.
На Linux-сервере 1С никакого cmd.exe нет. Вместо него используйте /bin/sh и скрипты. Всё, что описано ниже про cmd и COM, относится к Windows.
Есть и ограничение безопасного режима. В нём запуск внешних приложений запрещён, и платформа вызовет исключение. Так бывает в обработчиках внешних отчётов и обработок, которые выполняются в безопасном режиме, и в части регламентных сценариев.
Метод ЗапуститьПриложение: базовый способ
Синтаксис такой: ЗапуститьПриложение(СтрокаЗапуска, ТекущийКаталог, ДождатьсяЗавершения, КодВозврата). Обязательна только строка запуска. Остальные параметры по желанию.
Простой пример с ожиданием и проверкой кода возврата:
КодВозврата = 0;
ЗапуститьПриложение(
"cmd.exe /c ipconfig /all > C:\Temp\ip.txt",
"C:\Temp",
Истина,
КодВозврата);
Если КодВозврата <> 0 Тогда
ВызватьИсключение "Команда завершилась с кодом " + КодВозврата;
КонецЕсли;
Три нюанса, которые чаще всего ломают такой код.
- Ключ
/cвыполняет команду и закрывает окно. Ключ/kоставляет окно открытым, и приДождатьсяЗавершения = Истина1С зависнет, пока пользователь его не закроет. - Пути с пробелами нужно брать в кавычки, а саму строку после
/cоборачивать ещё раз. Рабочий вариант:cmd.exe /c ""C:\Program Files\Tool\run.bat" param1". - Перенаправление
>работает только внутри cmd. Если запуститьipconfig > file.txtбезcmd.exe /c, символ>уйдёт программе как обычный аргумент.
Кавычки в строке 1С удваиваются: "cmd.exe /c ""C:\My Folder\run.bat""". Ошибиться здесь проще всего, поэтому строку лучше собирать по частям и выводить в сообщение перед запуском.
Асинхронный запуск
В клиентском коде, особенно в веб-клиенте с расширением и в тонком клиенте с асинхронной моделью, есть НачатьЗапускПриложения. Он не блокирует интерфейс и вызывает оповещение, когда процесс закончится. Если команда идёт больше нескольких секунд, берите его: пользователь не увидит «зависшую» программу.
Метод КомандаСистемы
КомандаСистемы(Команда, ТекущийКаталог) тоже запускает команду ОС и сразу выполняет её через интерпретатор. Он проще для коротких вызовов вроде КомандаСистемы("ping 8.8.8.8"), но возможностей у него меньше. Кода возврата вы не получите, а на сервере такой вызов ведёт себя иначе, чем в клиенте. Для скриптов, где важен результат, берите ЗапуститьПриложение или COM.
Запуск через COM-объект WScript.Shell
Объект WScript.Shell даёт больше контроля: скрыть окно, получить код возврата, прочитать вывод.
Оболочка = Новый COMОбъект("WScript.Shell");
// Параметры Run: команда, стиль окна (0 - скрытое), ждать ли завершения
КодВозврата = Оболочка.Run("cmd.exe /c C:\Scripts\backup.bat", 0, Истина);
Параметр стиля окна 0 скрывает окно полностью. Это удобно для фоновых операций, когда чёрное окно на экране у бухгалтера только пугает. Значение 1 показывает окно в обычном виде.
Если нужен именно вывод команды, используйте метод Exec:
Оболочка = Новый COMОбъект("WScript.Shell");
Процесс = Оболочка.Exec("cmd.exe /c ipconfig");
Пока Процесс.Status = 0 Цикл
// ждём завершения; статус 0 означает, что процесс ещё работает
КонецЦикла;
Результат = Процесс.StdOut.ReadAll();
Цикл ожидания без паузы грузит процессор. Для коротких команд это терпимо. Для длинных лучше писать вывод в файл и читать его после завершения.
Сравним способы между собой:
| Способ | Скрытое окно | Код возврата | Вывод в 1С | Нужен COM |
|---|---|---|---|---|
ЗапуститьПриложение | Нет, окно видно | Да | Через файл | Нет |
КомандаСистемы | Нет | Нет | Через файл | Нет |
WScript.Shell.Run | Да | Да | Через файл | Да |
WScript.Shell.Exec | Да | Через ExitCode | Напрямую (StdOut) | Да |
COM-способ работает только в Windows и только там, где зарегистрирован WScript.Shell. В клиентском коде веб-клиента COM недоступен. На сервере он работает, но с оговорками про права, о которых ниже.
Bat-файлы и передача параметров
Когда команда длиннее двух строк, выносите её в bat-файл. Код 1С остаётся читаемым, а скрипт можно править без перекомпиляции конфигурации.
Пример bat-файла C:\Scripts\copy_base.bat:
@echo off
chcp 65001 > nul
set SRC=%~1
set DST=%~2
if "%SRC%"=="" exit /b 2
xcopy "%SRC%" "%DST%" /E /I /Y
exit /b %errorlevel%
Конструкции %~1 и %~2 забирают первый и второй параметры уже без кавычек. Так пути с пробелами не ломают скрипт. Проверка пустого параметра с кодом выхода 2 даёт 1С понятный сигнал, что файл вызвали неправильно.
Вызов из 1С:
Каталог = "C:\Scripts";
Исходный = "C:\1C Bases\Trade";
Целевой = "D:\Backup\Trade";
Команда = "cmd.exe /c """"" + Каталог + "\copy_base.bat"" """ + Исходный + """ """ + Целевой + """";
КодВозврата = 0;
ЗапуститьПриложение(Команда, Каталог, Истина, КодВозврата);
Если путей и параметров много, не склеивайте строку вручную. Соберите массив параметров, пропустите каждый через функцию, которая оборачивает значение в кавычки, и склейте через пробел.
Временные bat-файлы можно создавать из 1С через ТекстовыйДокумент и ПолучитьИмяВременногоФайла. Только помните, что кодировка файла влияет на кириллицу в путях: сохраняйте в той кодировке, которую ожидает cmd, и тестируйте на путях с русскими буквами.
Кодировка вывода
Консоль Windows по умолчанию выдаёт текст в кодовой странице 866, а 1С читает файл в UTF-8 или ANSI. Отсюда «кракозябры». Есть два выхода:
- перед командой выполните
chcp 65001, и вывод пойдёт в UTF-8; - при чтении файла в 1С явно укажите кодировку:
Чтение.Прочитать(Файл, КодировкаТекста.OEM)соответствует 866.
Второй способ надёжнее: он не зависит от настроек консоли конкретного сервера.
Коды возврата и разбор ошибок
Код 0 почти всегда значит успех. Что значат остальные, зависит от запущенной программы, а не от 1С. Для самого cmd.exe часто встречаются такие значения:
| Код | Типичная причина |
|---|---|
| 1 | Общая ошибка команды или неверный синтаксис |
| 2 | Файл или путь не найден |
| 5 | Отказано в доступе |
| 9009 | Команда не распознана (нет в PATH или опечатка) |
Эти значения не гарантируются для любой утилиты, так что документацию конкретной программы лучше проверять отдельно.
Рабочая схема обработки: пишете вывод и ошибки в лог-файл, проверяете код возврата, при ненулевом коде читаете лог и показываете пользователю последние строки. Для перенаправления ошибок используйте 2>&1, например: cmd.exe /c backup.bat > C:\Temp\log.txt 2>&1.
ЗапуститьПриложение с ДождатьсяЗавершения = Истина блокирует поток. На клиенте интерфейс замирает, на сервере занят рабочий процесс. Долгие операции запускайте асинхронно или отдельным регламентным заданием.
PATH и перезапустите службу сервера 1С.Права доступа и вопросы безопасности
Команда получает права того, кто её запустил. На клиенте это учётная запись пользователя Windows. На сервере это учётная запись, под которой работает служба Агент сервера 1С:Предприятия. Часто это отдельный пользователь usr1cv8 без доступа к пользовательским папкам и сетевым дискам.
Типичная история: код работает на тестовом компьютере и падает на сервере, потому что служба не видит сетевой ресурс Z:\. Подключённые диски привязаны к сеансу пользователя, службе они недоступны. Используйте UNC-пути вида \\server\share\file.txt и выдайте учётной записи службы права именно на эту шару.
Если в кластере включены профили безопасности, запуск приложений ОС тоже нужно разрешать отдельно. В настройках профиля есть список разрешённых для запуска исполняемых файлов, и без записи в нём вызов будет отклонён. Администрирование кластера делается через консоль администрирования серверов 1С.
Что ещё важно учесть:
- 🔒 не собирайте командную строку из данных, которые вводит пользователь. Иначе в строку можно подставить
& del *.*и выполнить лишнее; - 🔒 не запускайте с повышенными правами то, что можно сделать обычными;
- 🔒 антивирус может блокировать создание и запуск bat-файла из временного каталога. Если скрипт нужен постоянно, держите его в доверенной папке, а не создавайте на лету;
- 🔒 записывайте в журнал, что и когда запускалось, чтобы потом разобраться, кто вызвал команду.
Прежде чем запускать на сервере команду, которая останавливает службы, завершает процессы или удаляет файлы, предупредите пользователей. Такая команда оборвёт активные сеансы. Делайте это в нерабочее время.
Альтернативы и работа на сервере
Командную строку не всегда стоит вызывать. Многое 1С умеет сама, и встроенные средства проще сопровождать.
| Задача | Вместо cmd |
|---|---|
| Копирование, перемещение, удаление файлов | КопироватьФайл, ПереместитьФайл, УдалитьФайлы |
| Список файлов в каталоге | НайтиФайлы |
| Чтение и запись текстовых файлов | ТекстовыйДокумент, ЧтениеТекста, ЗаписьТекста |
| HTTP-запросы | HTTPСоединение, HTTPЗапрос |
| Архивы | ЗаписьZipФайла, ЧтениеZipФайла |
Встроенные методы работают одинаково в любой ОС, не требуют лишних прав на запуск программ и обходят проблемы с кодировкой. Cmd оправдан, когда нужна внешняя утилита: резервное копирование
базы через 1cv8.exe, работа с архиватором, сетевая диагностика, вызов планировщика.
Запуск на клиенте из серверного кода
Серверный код не может напрямую открыть программу на компьютере пользователя. Обычная схема такая: сервер готовит данные (файл, параметры) и возвращает их клиенту. Клиентская процедура получает файл через ПолучитьФайл и запускает программу уже на своей стороне. Если нужен запуск на сервере по расписанию, делайте регламентное задание: оно выполняется в серверном контексте, под учётной записью службы, и пользователь здесь не нужен.
Ожидание и таймауты
Если внешняя утилита может зависнуть, не вызывайте её с бесконечным ожиданием. Запустите асинхронно, вернитесь к ней по таймеру или в регламентном задании и проверьте, завершился ли процесс. Для проверки процессов в Windows годится tasklist, для принудительного завершения taskkill, но обращайтесь с ними осторожно: завершение не того процесса остановит работу других пользователей.
Частые вопросы
Можно ли запустить cmd из веб-клиента 1С?
Как скрыть чёрное окно cmd при запуске?
WScript.Shell.Run со стилем окна 0. Метод ЗапуститьПриложение окно не прячет.Как получить текст, который вывела команда?
> file.txt 2>&1) и прочитайте его через ТекстовыйДокумент. Либо используйте Exec и свойство StdOut.Почему в выводе вместо русских букв «кракозябры»?
КодировкаТекста.OEM при чтении или выполните chcp 65001 в начале команды.Работает ли такой запуск на сервере под Linux?
cmd.exe и WScript.Shell в Linux отсутствуют. Используйте shell-скрипты и запуск /bin/sh.