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

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

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

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

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

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

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

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

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

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

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

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

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

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

    возврат Процесс.ПолучитьПотокВывода().ПрочитатьКакСтроку()
;
ПотокиОшибокИВыводаСоединены
В том случае, когда экземпляр типа ПроцессОс получен вами извне (вы не создавали его в своем коде), это свойство позволяет узнать, в какой поток направляются ошибки:
  • Истина — ошибки направляются в стандартный поток вывода (System.out);
  • Ложь — ошибки направляются в стандартный поток ошибок (System.err).
Не забудьте: Управлять направлением ошибок вы можете в конструкторе ПроцессОс с помощью параметра СоединитьПотокиОшибокИВывода. Стандартно потоки соединены и ошибки направляются в стандартный поток вывода.

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

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

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

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