Почему при вызове КомандаСистемы зависает 1С и как правильно открывать файлы внешними программами?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке функционала выгрузки и открытия файлов на стороне клиента разработчики часто сталкиваются с ситуацией: при попытке открыть файл через процедуру КомандаСистемы появляется черное окно командной строки Windows (cmd.exe), программа 1С блокируется, а управление возвращается только после полного закрытия запущенного внешнего приложения (например, Блокнота или текстового редактора). Разберем причины такого поведения платформы и рассмотрим надежные способы запуска файлов и приложений.

Проанализируем механику работы процедуры КомандаСистемы. Данная процедура платформы не запускает файл напрямую через системные вызовы операционной системы, а обращается к командному интерпретатору cmd.exe /c <СтрокаКоманды>. Интерпретатор командной строки по умолчанию выполняет команду синхронно и ожидает завершения дочернего процесса. Пока внешний процесс активен, сеанс cmd.exe удерживает консольное окно открытым и не отдает управление платформе 1С:Предприятие, что приводит к полной блокировке интерфейса.

Способ 1. Использование встроенного метода ЗапуститьПриложение (Рекомендуемый)

Для запуска внешних программ и открытия файлов зарегистрированными в системе приложениями по умолчанию в платформе 1С предназначен метод ЗапуститьПриложение. В отличие от КомандаСистемы, данный метод обращается к системному API напрямую, минуя командный интерпретатор, благодаря чему черное консольное окно не появляется вовсе.

Посмотрим на синтаксис метода:

ЗапуститьПриложение(<СтрокаКоманды>, <ТекущийКаталог>, <ДождатьсяЗавершения>, <КодВозврата>)

По умолчанию третий параметр <ДождатьсяЗавершения> установлен в значение Ложь. Это означает, что приложение запустится асинхронно в отдельном процессе, а выполнение программного кода 1С продолжится сразу же.

Разберем пример открытия документа:


ПутьКФайлу = "C:\temp\document.docx";
ЗапуститьПриложение(ПутьКФайлу);

Операционная система сама определит сопоставленное расширению .docx приложение (например, MS Word) и откроет файл без блокировки клиентского сеанса 1С.

Если же перед нами стоит задача выполнить утилиту и обязательно дождаться результата ее работы, передадим в третий параметр значение Истина и получим код возврата:


КодВозврата = 0;
ЗапуститьПриложение("C:\Tools\converter.exe -input file.txt", , Истина, КодВозврата);
Если КодВозврата <> 0 Тогда
    Сообщить("Программа завершилась с ошибкой! Код: " + Строка(КодВозврата));
КонецЕсли;

Способ 2. Использование утилиты start внутри КомандаСистемы

Если логика алгоритма строго требует выполнения команды через командный интерпретатор ОС, необходимо принудительно отвязать дочерний процесс от сессии консоли с помощью встроенной системной утилиты Windows start.

Посмотрим на пример формирования строки команды:


ПутьКФайлу = "C:\temp\log.txt";
КомандаСистемы("start """" """ + ПутьКФайлу + """");

Утилита start создает отдельный независимый процесс для открытия файла и мгновенно возвращает управление интерпретатору. В результате окно cmd.exe сразу же закрывается, а управление возвращается в код 1С.

Способ 3. Асинхронные методы платформы 1С:Предприятие 8.3

В современных конфигурациях для предотвращения зависания интерфейса клиентского приложения рекомендуется использовать неблокирующие асинхронные вызовы платформы. Рассмотрим два основных варианта:

  1. Асинхронная процедура с оповещением:
    
    Оповещение = Новый ОписаниеОповещения("ПослеЗапускаПриложения", ЭтотОбъект);
    НачатьЗапускПриложения(Оповещение, "C:\temp\report.xlsx");
    
  2. Асинхронная функция с конструкцией Ждать:
    
    &НаКлиенте
    Асинх Процедура ОткрытьДокумент()
        Ждать ЗапуститьПриложениеАсинх("C:\temp\report.xlsx");
    КонецПроцедуры
    

Способ 4. Использование функций Библиотеки стандартных подсистем (БСП)

Если разработка ведется в типовой конфигурации на базе БСП, правильным решением будет вызов стандартизированных процедур подсистемы работы с файлами. Процедура ФайловаяСистемаКлиент.ОткрытьФайл обеспечивает безопасное открытие документов и проверяет потенциально опасные расширения исполняемых файлов.

Посмотрим на пример вызова:

ФайловаяСистемаКлиент.ОткрытьФайл("C:\temp\data.pdf");

Способ 5. Скрытие окна через COM-объект WScript.Shell

Для операционных систем семейства Windows существует альтернативный способ запуска через системный объект WScript.Shell. Метод Run позволяет точно определить режим отображения окна запускаемой программы.

Разберем программный код:


WshShell = Новый COMОбъект("WScript.Shell");
// Второй параметр 0 скрывает окно, третий параметр Ложь отключает ожидание завершения
WshShell.Run("notepad.exe ""C:\temp\file.txt""", 0, Ложь);

Ограничения и контекст выполнения

При выборе метода запуска необходимо учитывать следующие особенности платформы:

  1. Клиентский контекст: Процедуры КомандаСистемы и ЗапуститьПриложение выполняются исключительно на клиенте (в тонком или толстом клиенте) и недоступны на сервере 1С.
  2. Веб-клиент: Для вызова внешних программ из веб-клиента требуется наличие установленного расширения для работы с файлами.
  3. Кроссплатформенность: Методы через WScript.Shell и утилиту start работают только в среде Windows. Для обеспечения кроссплатформенности под Windows, Linux и macOS следует применять метод ЗапуститьПриложение или инструменты БСП.
← На главную