При разработке функционала выгрузки и открытия файлов на стороне клиента разработчики часто сталкиваются с ситуацией: при попытке открыть файл через процедуру КомандаСистемы появляется черное окно командной строки Windows (cmd.exe), программа 1С блокируется, а управление возвращается только после полного закрытия запущенного внешнего приложения (например, Блокнота или текстового редактора). Разберем причины такого поведения платформы и рассмотрим надежные способы запуска файлов и приложений.
Проанализируем механику работы процедуры КомандаСистемы. Данная процедура платформы не запускает файл напрямую через системные вызовы операционной системы, а обращается к командному интерпретатору cmd.exe /c <СтрокаКоманды>. Интерпретатор командной строки по умолчанию выполняет команду синхронно и ожидает завершения дочернего процесса. Пока внешний процесс активен, сеанс cmd.exe удерживает консольное окно открытым и не отдает управление платформе 1С:Предприятие, что приводит к полной блокировке интерфейса.
Для запуска внешних программ и открытия файлов зарегистрированными в системе приложениями по умолчанию в платформе 1С предназначен метод ЗапуститьПриложение. В отличие от КомандаСистемы, данный метод обращается к системному API напрямую, минуя командный интерпретатор, благодаря чему черное консольное окно не появляется вовсе.
Посмотрим на синтаксис метода:
ЗапуститьПриложение(<СтрокаКоманды>, <ТекущийКаталог>, <ДождатьсяЗавершения>, <КодВозврата>)
По умолчанию третий параметр <ДождатьсяЗавершения> установлен в значение Ложь. Это означает, что приложение запустится асинхронно в отдельном процессе, а выполнение программного кода 1С продолжится сразу же.
Разберем пример открытия документа:
ПутьКФайлу = "C:\temp\document.docx";
ЗапуститьПриложение(ПутьКФайлу);
Операционная система сама определит сопоставленное расширению .docx приложение (например, MS Word) и откроет файл без блокировки клиентского сеанса 1С.
Если же перед нами стоит задача выполнить утилиту и обязательно дождаться результата ее работы, передадим в третий параметр значение Истина и получим код возврата:
КодВозврата = 0;
ЗапуститьПриложение("C:\Tools\converter.exe -input file.txt", , Истина, КодВозврата);
Если КодВозврата <> 0 Тогда
Сообщить("Программа завершилась с ошибкой! Код: " + Строка(КодВозврата));
КонецЕсли;
Если логика алгоритма строго требует выполнения команды через командный интерпретатор ОС, необходимо принудительно отвязать дочерний процесс от сессии консоли с помощью встроенной системной утилиты Windows start.
Посмотрим на пример формирования строки команды:
ПутьКФайлу = "C:\temp\log.txt";
КомандаСистемы("start """" """ + ПутьКФайлу + """");
Утилита start создает отдельный независимый процесс для открытия файла и мгновенно возвращает управление интерпретатору. В результате окно cmd.exe сразу же закрывается, а управление возвращается в код 1С.
В современных конфигурациях для предотвращения зависания интерфейса клиентского приложения рекомендуется использовать неблокирующие асинхронные вызовы платформы. Рассмотрим два основных варианта:
Оповещение = Новый ОписаниеОповещения("ПослеЗапускаПриложения", ЭтотОбъект);
НачатьЗапускПриложения(Оповещение, "C:\temp\report.xlsx");
&НаКлиенте
Асинх Процедура ОткрытьДокумент()
Ждать ЗапуститьПриложениеАсинх("C:\temp\report.xlsx");
КонецПроцедуры
Если разработка ведется в типовой конфигурации на базе БСП, правильным решением будет вызов стандартизированных процедур подсистемы работы с файлами. Процедура ФайловаяСистемаКлиент.ОткрытьФайл обеспечивает безопасное открытие документов и проверяет потенциально опасные расширения исполняемых файлов.
Посмотрим на пример вызова:
ФайловаяСистемаКлиент.ОткрытьФайл("C:\temp\data.pdf");
Для операционных систем семейства Windows существует альтернативный способ запуска через системный объект WScript.Shell. Метод Run позволяет точно определить режим отображения окна запускаемой программы.
Разберем программный код:
WshShell = Новый COMОбъект("WScript.Shell");
// Второй параметр 0 скрывает окно, третий параметр Ложь отключает ожидание завершения
WshShell.Run("notepad.exe ""C:\temp\file.txt""", 0, Ложь);
При выборе метода запуска необходимо учитывать следующие особенности платформы:
КомандаСистемы и ЗапуститьПриложение выполняются исключительно на клиенте (в тонком или толстом клиенте) и недоступны на сервере 1С.WScript.Shell и утилиту start работают только в среде Windows. Для обеспечения кроссплатформенности под Windows, Linux и macOS следует применять метод ЗапуститьПриложение или инструменты БСП.