Как выполнить консольную команду и получить результат ее работы в 1С?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При интеграции 1С с системными утилитами операционной системы часто требуется не просто запустить внешнюю команду, но и получить результат её выполнения (например, статус выполнения утилиты ping, вывод утилит сетевой диагностики, архиваторов или консольных скриптов).

Штатная процедура 1С КомандаСистемы() запускает указанное приложение синхронно, однако она не возвращает результат работы команды и не позволяет напрямую перехватить текстовый поток вывода (stdout или stderr) в переменную. Разберем по шагам несколько надежных способов решения этой задачи.

Вариант 1. Прямой перехват потока вывода через WScript.Shell.Exec

Рассмотрим использование системного COM-объекта WScript.Shell и его метода Exec. Этот метод создает дочерний процесс и предоставляет прямой программный доступ к стандартным потокам ввода-вывода (StdIn, StdOut, StdErr).

Посмотрим на пример реализации с построчным чтением потока вывода:


WshShell = СоздатьОбъект("WScript.Shell");
WshExec = WshShell.Exec("ping 192.168.2.1");
TextStream = WshExec.StdOut;

Вывод = "";
Пока TextStream.AtEndOfStream = 0 Цикл
    // Вычитываем строку из потока вывода
    СтрокаВывода = TextStream.ReadLine();
    Вывод = Вывод + СтрокаВывода + РазделительСтрок;
КонецЦикла;

Сообщить(Вывод);

Проанализируем важные технические нюансы этого метода:

  1. Кодировка текста: Консольные утилиты Windows возвращают русскоязычный текст в кодировке OEM (CP866), тогда как интерфейс 1С работает в кодировке ANSI (Windows-1251). Для корректного отображения кириллицы прочитанные строки необходимо перекодировать (например, с помощью внешней функции преобразования OEM в ANSI).
  2. Отображение окна: Метод Exec по своей архитектуре всегда открывает черное окно консоли во время работы дочернего процесса. Если требуется полностью скрытое фоновое выполнение, следует использовать метод Run с перенаправлением в файл.
  3. Буфер потоков вывода: Размер буфера потока в Windows ограничен. Если внешняя утилита выводит слишком большой объем данных или пишет ошибки в поток StdErr, процесс может приостановиться в ожидании освобождения буфера. При выполнении сложных команд рекомендуется последовательно проверять статус процесса WshExec.Status.

Вариант 2. Скрытый запуск команды с перенаправлением вывода в файл

Если появление черного окна консоли нежелательно для пользователя, разберем наиболее стабильный способ: запуск командного интерпретатора в скрытом режиме с перенаправлением потока (>) во временный текстовый файл с последующим чтением через объект Текст.

Посмотрим на пример программной реализации:


КаталогВременныхФайлов = КаталогВременныхФайлов();
ИмяФайла = КаталогВременныхФайлов + "cmd_output.txt";

WshShell = СоздатьОбъект("WScript.Shell");
// Запускаем командный интерпретатор %ComSpec% /c
// 0 - скрытый режим окна, 1 - ожидать завершения команды
Команда = "%ComSpec% /c ping 192.168.2.1 > """ + ИмяФайла + """";
КодВозврата = WshShell.Run(Команда, 0, 1);

ФайлВывода = СоздатьОбъект("Текст");
// Устанавливаем кодовую страницу OEM (DOS/CP866) для корректного чтения кириллицы
ФайлВывода.КодоваяСтраница(1);

Если ФС.СуществуетФайл(ИмяФайла) = 1 Тогда
    ФайлВывода.Открыть(ИмяФайла);
    
    Для НомерСтроки = 1 По ФайлВывода.КоличествоСтрок() Цикл
        Сообщить(ФайлВывода.ПолучитьСтроку(НомерСтроки));
    КонецЦикла;
    
    // Закрываем и удаляем временный файл
    ФайлВывода.Очистить();
    ФС.УдалитьФайл(ИмяФайла);
Иначе
    Сообщить("Не удалось получить результат выполнения команды.");
КонецЕсли;

В этом варианте метод КодоваяСтраница(1) объекта Текст автоматически преобразует символы из DOS-кодировки в привычный для 1С формат ANSI, исключая появление нечитаемых символов.

Вариант 3. Проверка сетевой доступности через WMI (без запуска консоли)

Если основной задачей вызова ping является проверка доступности определенного узла сети, более производительным и надежным решением будет использование системного интерфейса WMI (Windows Management Instrumentation).

Разберем пример запроса к WMI-классу Win32_PingStatus:


WbemLocator = СоздатьОбъект("WbemScripting.SWbemLocator");
WbemServices = WbemLocator.ConnectServer(".", "root\cimv2");

Узел = "192.168.2.1";
Запрос = "SELECT * FROM Win32_PingStatus WHERE Address = '" + Узел + "'";
Результаты = WbemServices.ExecQuery(Запрос);

Для Каждого Объекта Из Результаты Цикл
    Если Объекта.StatusCode = 0 Тогда
        Сообщить("Узел " + Узел + " доступен. Время ответа: " + Строка(Объекта.ResponseTime) + " мс");
    Иначе
        Сообщить("Узел " + Узел + " недоступен. Код ошибки: " + Строка(Объекта.StatusCode));
    КонецЕсли;
КонецЦикла;

Преимущества работы через WMI: выполнение происходит полностью в фоновом режиме, не создает временных файлов на диске, не зависит от языка операционной системы и не требует последующего разбора текстовых строк.

← На главную