В процессе автоматизации администрирования и интеграции систем часто возникает необходимость программно запустить одну информационную базу 1С из другой. Например, для выгрузки файлов конфигурации, выполнения пакетных обновлений или перезаписи общих макетов. Самым популярным инструментом для этого является метод ЗапуститьПриложение. Однако при переносе работающего кода на сервер разработчики регулярно сталкиваются с критической проблемой: процесс запускается, зависает в памяти сервера, блокирует файлы базы данных (особенно в файловом варианте) и намертво останавливает выполнение фонового задания.
В этой статье мы подробно разберем, почему зависает Конфигуратор при вызове из кода 1С, как правильно настроить параметры командной строки, как реализовать надежный механизм отслеживания запуска с контролем таймаута на стороне операционной системы, а также рассмотрим более изящные архитектурные альтернативы.
При запуске 1С в интерактивном режиме на рабочем компьютере пользователя любые проблемы (неверный пароль, предложение обновить конфигурацию, предупреждение о несовпадении версий платформы) выводятся в виде диалоговых окон. Пользователь нажимает кнопку, и процесс идет дальше.
На сервере (в контексте службы 1C:Enterprise) интерактивного пользователя нет. Процессы выполняются в так называемой "Сессии 0", которая полностью изолирована от графического интерфейса. Если запущенный процесс 1cv8.exe пытается вывести на экран любое, даже самое незначительное предупреждение или вопрос, он делает это в "невидимый" рабочий стол. Процесс бесконечно ожидает клика по кнопке ОК или Отмена, которой физически не существует. В результате:
Чтобы избежать подобных "зависаний", необходимо придерживаться строгих правил формирования строки запуска и использовать механизмы принудительного контроля времени выполнения процесса.
Для предотвращения появления скрытых модальных окон при пакетном запуске платформы 1С обязательно используйте специализированные ключи командной строки.
Проанализируем ключевые параметры, которые должны присутствовать в вашей строке запуска:
/NonInteractive — самый важный ключ для работы в фоновом режиме. Он заставляет платформу подавлять любые диалоговые окна, автоматически выбирая ответы по умолчанию. Если возникает критическая ошибка, процесс мгновенно завершится с соответствующим кодом возврата, вместо того чтобы зависнуть./Out "ПутьКФайлуЛога" — перенаправляет стандартный вывод консоли и сообщения об ошибках в текстовый файл. Без этого ключа вы никогда не узнаете, что именно пошло не так внутри запускаемого процесса./DumpErrorLog "ПутьКФайлуОшибок" — записывает подробную информацию о критических сбоях платформы в лог-файл.Рассмотрим пример формирования безопасной строки запуска Конфигуратора для выгрузки файлов конфигурации:
ПутьКПлатформе = "C:\Program Files\1cv8\8.3.22.1709\bin\1cv8.exe";
СтрокаЗапуска = """" + ПутьКПлатформе + """ DESIGNER "
+ "/F """ + ПутьКБазе + """ "
+ "/N """ + ИмяПользователя + """ "
+ "/P """ + Пароль + """ "
+ "/NonInteractive "
+ "/DumpConfigToFiles """ + КаталогВыгрузки + """ "
+ "/Out """ + КаталогВыгрузки + "\log.txt"" -NoTruncate";
Обратите внимание: настоятельно рекомендуется указывать прямой путь к конкретной версии исполняемого файла 1cv8.exe, а не использовать общий загрузчик 1cestart.exe. Загрузчик может инициировать процедуру поиска и обновления версии платформы, что гарантированно приведет к зависанию в фоновом режиме на сервере.
Стандартный метод 1С ЗапуститьПриложение(СтрокаЗапуска, , Истина) полностью останавливает выполнение вашего кода до тех пор, пока внешняя программа не завершит работу. Если внешняя программа зависнет, фоновое задание прервется только по системному таймауту кластера 1С, но дочерний процесс операционной системы при этом останется "зомби-процессом" в памяти сервера.
Чтобы получить полный контроль над процессом, воспользуемся системным COM-объектом WScript.Shell. Вместо синхронного ожидания мы запустим процесс асинхронно, будем опрашивать его состояние в цикле и принудительно завершим его, если он превысит лимит отведенного времени.
Рассмотрим подробный программный код реализации этой схемы на сервере под управлением ОС Windows:
Функция ВыполнитьКомандуСТаймаутом(СтрокаЗапуска, ТаймаутСекунд) Экспорт
// Создаем системный COM-объект для управления процессами
Shell = Новый COMОбъект("WScript.Shell");
Попытка
// Метод Exec запускает приложение асинхронно и возвращает объект управления WshScriptExec
Процесс = Shell.Exec(СтрокаЗапуска);
Исключение
ЗаписатьВЖурналРегистрации("ЗапускПриложения.Ошибка",
УровеньЖурналаРегистрации.Ошибка, , ,
"Не удалось запустить приложение: " + ОписаниеОшибки());
Возврат Ложь;
КонецПопытки;
ИдентификаторПроцесса = Процесс.ProcessID;
ВремяСтарта = ТекущаяДата();
УспешноЗавершено = Ложь;
// Цикл ожидания завершения с контролем таймаута
Пока Истина Цикл
// Статус: 0 - выполняется, 1 - завершено успешно, 2 - завершено с ошибкой
Если Процесс.Status <> 0 Тогда
УспешноЗавершено = Истина;
Прервать;
КонецЕсли;
// Проверяем превышение таймаута
Если (ТекущаяДата() - ВремяСтарта) > ТаймаутСекунд Тогда
Прервать;
КонецЕсли;
// Микропауза на сервере, чтобы не нагружать процессор на 100%
ПаузаНаСервере(1);
КонецЦикла;
// Если процесс завис и превысил таймаут, принудительно уничтожаем его в ОС
Если Не УспешноЗавершено Тогда
ЗаписатьВЖурналРегистрации("ЗапускПриложения.ПревышенТаймаут",
УровеньЖурналаРегистрации.Предупреждение, , ,
"Процесс " + ИдентификаторПроцесса + " превысил лимит ожидания и будет принудительно завершен.");
Попытка
// Пытаемся завершить процесс штатными методами COM-объекта
Процесс.Terminate();
Исключение
// Альтернативный жесткий способ завершения через утилиту taskkill
КомандаУбийства = "taskkill /F /PID " + Формат(ИдентификаторПроцесса, "ЧГ=0");
Shell.Run(КомандаУбийства, 0, Истина);
КонецПопытки;
Возврат Ложь;
КонецЕсли;
КодВозврата = Процесс.ExitCode;
Возврат (КодВозврата = 0);
КонецФункции
Процедура ПаузаНаСервере(Секунды)
// Трюк для реализации задержки выполнения на сервере без использования внешних компонент
КомандаСистемы = "ping -n " + Формат(Секунды + 1, "ЧГ=0") + " 127.0.0.1 > nul";
ЗапуститьПриложение(КомандаСистемы, , Истина);
КонецПроцедуры
Данный подход гарантирует, что вызывающий поток 1С не зависнет навсегда. Даже если запускаемый Конфигуратор заблокирует файлы или выдаст ошибку авторизации, по истечении указанного таймаута процесс гарантированно будет "убит", а ресурсы операционной системы освобождены.
Несмотря на наличие программных решений по борьбе с зависаниями, запуск Конфигуратора из кода "на лету" для изменения метаданных или макетов — это архитектурно тяжелая, нестабильная и небезопасная операция. Для изменения конфигурации требуется монопольный доступ, что парализует работу пользователей.
Проанализируем альтернативные и более надежные способы реализации задачи хранения и изменения версионных данных или макетов:
Вместо размещения макетов внутри конфигурации (в дереве метаданных) перенесите их в базу данных. Создайте справочник или Регистр сведений с реквизитом типа ХранилищеЗначения.
В этом случае, чтобы перезаписать макет или прочитать его версию, вам не понадобятся Конфигуратор и запуск сторонних приложений. Все операции выполняются обычным транзакционным кодом за доли секунды без каких-либо блокировок.
Если макет обязательно должен являться частью метаданных системы, его можно вынести в отдельное расширение конфигурации. Подключение, обновление и применение расширений программным путем происходит значительно быстрее и безопаснее, чем модификация основной конфигурации, и накладывает существенно меньше блокировок на базу данных.
Если у вас развернуто множество распределенных баз данных, не обязательно публиковать каждую из них на веб-сервере. Вы можете реализовать обратную схему: целевые базы периодически (по расписанию через регламентные задания) обращаются к единому центральному HTTP-сервису, запрашивают актуальную информацию о макетах/версиях и обновляют свои локальные данные. Это полностью исключает необходимость прямого сетевого подключения к базам и их конфигураторам.
Используя предложенные методы контроля процессов и оптимизировав архитектуру хранения макетов, вы полностью избавите свою систему от серверов-заложников зависших процессов 1С и обеспечите непрерывную стабильную работу бизнес-приложений.