Как выполнить внешнюю программу, вызвав конечную точку API.

Иногда нашему приложению необходимо разрешить пользователям выполнять внешнюю программу, вызывая конечную точку API. Внешняя программа может быть сценарием, сторонним программным обеспечением или исполняемым файлом, написанным на устаревшей платформе.

Чтобы запустить фоновый процесс, который не может быть легко интегрирован в современную структуру или инфраструктуру, обычно мы хотим разделить системы. Например, мы можем позволить нашей системе делегировать внешний процесс агенту управления заданиями, например, Jenkins. Другой распространенный подход - запустить команду в очереди сообщений, затем внешний исполняемый файл подписывается на событие и предпринимает соответствующие действия.

Жизнь бывает. Когда мы не можем позволить себе развернуть набор инфраструктуры, мы должны позволить нашему приложению напрямую вызывать интерфейс командной строки. В этом посте будет рассмотрен пример использования, когда helloworld.exeWindows) выполняется из конечной точки веб-API ASP.NET Core. Это решение, возможно, потребуется немного изменить, если ваше приложение работает в другой ОС. Полное решение можно найти в этом репозитории GitHub.

Покажи мне код

Сначала мы создаем надуманную программу под названием helloworld.exe в .NET framework. Это helloworld.exe имитирует внешнюю программу, которая будет запускаться проектом веб-API ASP.NET Core. Эта программа, см. Фрагмент кода ниже, просто записывает журналы в консоль и создает файл на диске.

Мы строим проект для создания helloworld.exe файла и знаем его местоположение.

Затем мы создаем простой проект веб-API ASP.NET Core. В демонстрационных целях мы модифицируем метод действия Get(int id) в классе ValuesController следующим образом.

Строка 7 создает экземпляр Процесса, который позволяет нашему приложению запускать и останавливать локальные системные процессы. Оператор using уничтожит объект process по завершении использования.
Строка 9 указывает путь к исполняемому файлу. Здесь я использую относительный путь, который следует заменить вашим фактическим путем, или абсолютный путь, основанный на вашем дизайне. Следует отметить, что учетная запись приложения должна иметь соответствующие разрешения для исполняемой программы.
Строка 10 устанавливает аргументы, что является необязательным. В этом демонстрационном проекте строка id, взятая из URL-адреса конечной точки API, передается программе helloworld.exe.
Строки 13 и 14 запрещают процессу создавать какие-либо окна оболочки и не использовать ShellExecute. Мы устанавливаем UseShellExecute на false, потому что мы указываем исполняемый файл напрямую, задав путь к свойству FileName.
Строки 15–19 настраивают вывод консоли в исполняемой программе для перенаправления в стандартный поток вывода вызывающего объекта, который в данном случае является выводом консоли.
Строка 21 запускает процесс, а строки 22 и 23 начинают собирать выходной поток. Строка 24 ожидает завершения процесса и записывает код выхода.

Если мы обслуживаем проект веб-API и вызываем конечную точку API, то будет выполнена helloworld.exe программа. На следующем снимке экрана показан пример вывода консоли. В выводе консоли первая и последняя строки относятся к конечной точке API, другие строки перенаправляются из вывода консоли при запуске программы helloworld.exe.

Виола ~ Похоже на кусок пирога.

Пока вы не попытаетесь найти вновь созданный файл, _17 _...

Предупреждение: относительный путь во внешнем исполняемом файле

Мы использовали относительный путь в программе helloworld.exe. Обратите внимание на строку вывода консоли «file path: App_Data\123.txt». Как вы думаете, где будут находиться папка App_Data и файл 123.txt? В папке, где находится файл helloworld.exe? Или в папке Content Root проекта веб-API?

Ответ находится в корневой папке содержимого. Это означает, что процесс, запущенный из проекта веб-API, наследует рабочий каталог.

Чтобы проверить это, мы можем использовать такой код, как строки 12 и 13, чтобы распечатать текущий рабочий каталог. Пример выходных данных консоли показан на следующем снимке экрана, который подтверждает, что текущий рабочий каталог в командной строке является корневой папкой содержимого проекта веб-API.

Если у вас есть контроль над внешней исполняемой программой, вы, вероятно, захотите разрешить относительный путь на основе базового каталога сборки с помощью AppDomain.CurrentDomain.BaseDirectory. Таким образом, исполняемый файл может правильно найти файл настроек или другие ресурсы.

Это все на сегодня. Запуск процесса внутри .NET Core или проекта ASP.NET Core прост и решает некоторые простые проблемы. Опять же, полное решение можно найти в этом репозитории GitHub.

Спасибо за прочтение.