При интеграции 1С с внешними консольными программами разработчики часто сталкиваются с ситуацией: команда отлично выполняется вручную через командную строку Windows (cmd.exe), но при вызове из кода 1С через КомандаСистемы или ЗапуститьПриложение процесс завершается мгновенно, а ожидаемый результат (например, конвертированный файл) не создается. Разберем эту проблему на примере конвертации файлов PDF в изображения JPG с помощью популярной утилиты ImageMagick.
Проанализируем ситуацию: когда вы вызываете внешнее приложение напрямую или через сформированный пакетный файл (.bat), текущим рабочим каталогом процесса становится папка, из которой был произведен запуск (в 1С это часто каталог платформы или папка временных файлов пользователя). Многие утилиты, включая ImageMagick, используют динамическую загрузку внешних модулей кодирования (например, modules\coders\IM_MOD_RL_PNG_.dll) и сторонних библиотек. Если путь к программе не прописан в системной переменной среды PATH, процесс не может найти свои динамические библиотеки и аварийно завершается с кодом ошибки 1 и сообщением вида unable to load module или no decode delegate for this image format.
Если внешний процесс завершается без видимого результата, первым делом выясним причину сбоя. Для этого нужно получить код возврата и прочитать текст ошибки консоли.
Рассмотрим, как запустить команду с ожиданием завершения и выводом кода возврата в 1С:
КодВозврата = 0;
// Третий параметр "Истина" включает режим ожидания завершения
ЗапуститьПриложение(ИмяФайлаБат, , Истина, КодВозврата);
Сообщить("Код завершения процесса: " + КодВозврата);
Если код возврата не равен нулю, произошла ошибка. Чтобы увидеть сам текст ошибки, можно временно добавить команду pause в конец bat-файла либо перенаправить стандартные потоки вывода и ошибок в текстовый лог:
ПутьКЛогу = ПолучитьИмяВременногоФайла("txt");
КомандаСЛогированием = СтрокаКоманды + " > """ + ПутьКЛогу + """ 2>&1";
// После выполнения считываем текст ошибки
ТекстЛога = Новый ЧтениеТекста(ПутьКЛогу, КодировкаТекста.OEM);
ВыводКонсоли = ТекстЛога.Прочитать();
ТекстЛога.Закрыть();
Сообщить(ВыводКонсоли);
Чтобы приложение гарантированно нашло все свои библиотеки и конфигурационные файлы, необходимо явно задать для него текущую рабочую директорию. Сделать это можно двумя способами.
Способ 1. Использование штатного параметра платформы 1С (рекомендуемый)
Метод ЗапуститьПриложение принимает вторым параметром ТекущийКаталог. В этом случае отпадает необходимость создания промежуточных .bat файлов, а запуск выполняется напрямую:
КаталогУтилиты = "c:\Program Files\ImageMagick-7.0.5-Q16\";
ИсполняемыйФайл = КаталогУтилиты + "magick.exe";
ФайлPDF = "C:\Temp\Document.pdf[0]"; // [0] означает только первую страницу
ФайлJPG = ПолучитьИмяВременногоФайла("jpg");
СтрокаПараметров = """" + ИсполняемыйФайл + """ convert -density 300 """ + ФайлPDF + """ """ + ФайлJPG + """";
КодВозврата = 0;
ЗапуститьПриложение(СтрокаПараметров, КаталогУтилиты, Истина, КодВозврата);
Если КодВозврата <> 0 Тогда
ВызватьИсключение "Ошибка конвертации документа. Код: " + КодВозврата;
КонецЕсли;
Способ 2. Установка каталога внутри BAT-файла
Если сценарий требует обязательного использования пакетного файла, необходимо перед выполнением основной утилиты переключить диск и каталог с помощью команды cd /d:
ПутьBAT = ПолучитьИмяВременногоФайла("bat");
ФайлJPG = ПолучитьИмяВременногоФайла("jpg");
Запись = Новый ЗаписьТекста(ПутьBAT, КодировкаТекста.OEM);
Запись.ЗаписатьСтроку("cd /d ""c:\Program Files\ImageMagick-7.0.5-Q16\""");
Запись.ЗаписатьСтроку("magick.exe convert -density 300 """ + ПутьКФайлуPDF + "[0]"" """ + ФайлJPG + """");
Запись.Закрыть();
КодВозврата = 0;
ЗапуститьПриложение(ПутьBAT, , Истина, КодВозврата);
Разберем специфические особенности, которые могут помешать корректной работе конвертера:
temp-0.jpg, temp-1.jpg), и файл с точным именем temp.jpg существовать не будет. Чтобы конвертировать первую страницу, укажите индекс в скобках: файл.pdf[0].USR1CV8). Убедитесь, что у этой учетной записи есть права на чтение каталога утилиты, а также права на чтение и запись во временные папки.Если требуется скрывать всплывающее черное окно консоли или перехватывать потоки данных в фоновом режиме, можно использовать системный COM-объект WScript.Shell:
WshShell = Новый COMОбъект("WScript.Shell");
WshShell.CurrentDirectory = "c:\Program Files\ImageMagick-7.0.5-Q16\";
Команда = "magick.exe convert -density 300 """ + ПутьКФайлуPDF + "[0]"" """ + ФайлJPG + """";
// 0 - скрыть окно, Истина - ожидать завершения
КодВозврата = WshShell.Run(Команда, 0, Истина);
Если КодВозврата <> 0 Тогда
Сообщить("Не удалось выполнить конвертацию, код: " + КодВозврата);
КонецЕсли;