Процессы операционной системы

При обсуждении выполнения каких-либо программ под управлением операционной системы используется термин процесс. Процессом будем называть отражение исполняемого файла на ресурсы компьютера: занятая оперативная память, загруженный в память исполняемый код и т. д. «1С:Шина» позволяет работать с процессами операционной системы, но не с любым процессом, а только с теми, которые запущены из текущего сценария. Другими словами, вы не можете подключиться к процессу уже запущенного приложения. В то же время, если вы сами запускаете какое-либо приложение, то процесс данного приложения будет вам доступен и вы сможете с ним взаимодействовать.

Для работы с процессами операционной системы предназначен тип ПроцессОс. Важно понимать, что экземпляр типа ПроцессОс не является интерпретатором команд операционной системы.

Работа с процессом состоит из нескольких шагов, описанных ниже.

1. Создание нового процесса

Экземпляр ПроцессОс создается с помощью конструктора. Если приложение, с которым будет связан процесс, должно получить на вход какие-то параметры, эти параметры необходимо указать именно при создании экземпляра ПроцессОс. Создание процесса не означает, что приложение будет запущено. Также имеется возможность указать, что стандартные потоки вывода и ошибок можно объединить.

2. Запуск созданного процесса.

Для запуска процесса предназначен метод Запустить(). Запускаемый процесс наследует переменные окружения родительского процесса. При запуске можно указать текущий каталог для запускаемого процесса с помощью параметра Каталог.

3. Работа с процессом.

«1С:Шина» предоставляет следующие возможности по работе с процессом:

Живой()
Выполняет проверку, что с экземпляром ПроцессОс еще ассоциирован какой-то процесс операционной системы
Остановить()
Останавливает процесс
ПолучитьPid()
Получает идентификатор процесса в терминах используемой операционной системы
Возможная проблема: Реальный идентификатор процесса будет получен только в том случае, если «1С:Шина» работает с использованием Java версии 9 и выше.
ОжидатьЗавершения()
Ожидает завершения работы процесса
ПолучитьПотокВвода()
Получает стандартный ввод запущенного приложения. Он возвращает экземпляр типа ПотокЗаписи. В него вы можете записывать текст, который будет передан экземпляру типа ПроцессОС.
пер ВходныеДанные = Процесс.ПолучитьПотокВвода()
ВходныеДанные.Записать("Текст как входные данные Процесса")
ПолучитьПотокВвода() можно вызвать только после запуска ПроцессОС. Пока вы не закроете полученный таким образом ПотокЗаписи, ПроцессОС будет ожидать входные данные. Ниже приведен пример передачи строки поиска командному интерпретатору cmd.
метод Grep(Вход: Строка, Фильтр: Строка): Строка
    // Аналог grep в Windows. Требует входных данных
    пер Процесс = новый ПроцессОс(cmd.exe", ["/c", "findstr %Фильтр"])
    
    // Указать входные данные можно только после старта процесса
    Процесс.Запустить()

    область
        исп Поток = Процесс.ПолучитьПотокВвода()
        Поток.Записать(Вход)
    ; // Даем понять, что входных данных процесс может больше не ожидать

    возврат Процесс.ПолучитьПотокВывода().ПрочитатьКакСтроку()
;
ПолучитьПотокВывода()
Получает стандартный вывод запущенного приложения. Необходимо получить экземпляр типа ПотокЧтения (ПроцессОС.ПолучитьПотокВывода()) и затем читать из ПотокЧтения информацию, которая туда помещается процессом (ПотокЧтения.ПрочитатьКакСтроку()). С помощью этого метода можно реализовать сценарий, который будет анализировать вывод другого приложения и использовать полученные данные для принятия решений в режиме реального времени.
Возможная проблема: Если настроен вывод в консоль, то при чтении из нее вы можете столкнуться с неправильной кодировкой символов кириллицы. В этом случае передавайте нужную кодировку параметром в метод ПрочитатьКакСтроку().
ПолучитьПотокОшибок()
Получить стандартный поток ошибок запущенного приложения.
ПотокиОшибокИВыводаСоединены
Если экземпляр типа ПроцессОс получен вами извне (вы не создавали его в своем коде), это свойство позволяет узнать, в какой поток направляются ошибки:
  • Истина — ошибки направляются в стандартный поток вывода;
  • Ложь — ошибки направляются в стандартный поток ошибок.
Не забудьте: Управлять направлением ошибок вы можете в конструкторе ПроцессОс с помощью параметра СоединитьПотокиОшибокИВывода. Как правило, потоки соединены, и ошибки направляются в стандартный поток вывода.
Чтение потока вывода частями
Методы ПроцессОС.ПолучитьПотокВывода() и ПроцессОС.ПолучитьПотокОшибок() позволяют читать данные выходного потока частями, как показано в примере ниже:
метод ВыполнитьКомандуИВернутьРезультат(
    ИмяКоманды: Строка, 
    Параметры: ЧитаемыйМассив<Объект>): ЧитаемыйМассив<Строка>
	
    пер Процесс = новый ПроцессОс(ИмяКоманды, Параметры, Ложь)
    Процесс.Запустить()
    исп РезультатВыполненияСкрипта = Процесс.ПолучитьПотокВывода()
    знч Вывод: Массив<Строка> = []
 
    пока не Процесс.ОжидатьЗавершения(60с)
        знч ТекстРезультата = РезультатВыполненияСкрипта.ПрочитатьКакСтроку()
        если не ТекстРезультата.Пусто()
            Вывод.Добавить(ТекстРезультата)
        ;
    ;
 
    знч ТекстРезультата = РезультатВыполненияСкрипта.ПрочитатьКакСтроку()
    если не ТекстРезультата.Пусто()
        Вывод.Добавить(ТекстРезультата)
    ;
    возврат Вывод
;
Для получения данных всего потока необходимо дождаться завершения процесса с помощью метода ПроцессОС.ОжидатьЗавершения(). Поток вывода будет закрыт автоматически при выходе экземпляра ПроцессОс из области видимости.
Организовать конвейер процессов (pipe)
Конвейер (pipe) — это способ межпроцессного взаимодействия, при котором выходной поток одного процесса является входным потоком для другого. Вы можете создавать конвейеры с помощью метода ПроцессОС.ПередатьВыводВ(). Он добавляет новый процесс в конвейер на основе команды и аргументов. К процессу в конвейере применяются те же настройки, что и к исходному ПроцессОс. Метод возвращает текущий экземпляр ПроцессОс, в котором выходной поток соответствует выходному потоку нового процесса.
Возможная проблема: Для корректной работы метода необходимо, чтобы экземпляр работал в окружении Java 9+.
Ниже приведен пример просмотра папки и поиска подстроки в Windows:
метод ПросмотретьПапкуИНайтиПодстроку(ПапкаДляПросмотра: Строка, Фильтр: Строка): Строка
    // Аналог ls в Windows
    пер Процесс = новый ПроцессОс("cmd.exe", ["/c", "dir " + ПапкаДляПросмотра])
    
    // Передадим вывод аналогу grep в Windows
    Процесс.ПередатьВыводВ("cmd.exe", ["/c", "findstr " + Фильтр])

    // Запустим конвейер
    Процесс.Запустить()

    возврат Процесс.ПолучитьПотокВывода().ПрочитатьКакСтроку()
;

4. Обработка завершения работы процесса.

Чтобы обработать завершение работы процесса, можно проанализировать код возврата приложения, полученный с помощью метода ПолучитьКодВозврата():

метод РаботаСПроцессом(): Строка
    // Создадим процесс и разделим потоки ошибок и вывода
    пер Процесс = новый ПроцессОс("cmd.exe", ["/c", "dir c:\\windows /N /4"], СоединитьПотокиОшибокИВывода = Ложь)
    
    Процесс.Запустить()
    
    // Код 0 считается нормальным завершением процесса
    если Процесс.ПолучитьКодВозврата() == 0
        возврат Процесс.ПолучитьПотокВывода().ПрочитатьКакСтроку()
    иначе
        возврат Процесс.ПолучитьПотокОшибок().ПрочитатьКакСтроку()
    ;
;