Как закрыть 1С программно, которая запущена скриптом на выполнение внешней обработки

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

При автоматизации рутинных задач часто возникает ситуация, когда 1С запускается из командного файла (bat, cmd) или скрипта для выполнения конкретной внешней обработки. Однако стандартный запуск через ключ /Execute таит в себе проблему: если в самой внешней обработке не прописана команда ЗавершитьРаботуСистемы(), окно программы останется открытым, а вызывающий скрипт будет бесконечно ожидать завершения процесса. Ситуация осложняется, если внешние обработки часто меняются разными разработчиками, и нельзя гарантировать наличие кода закрытия в каждой из них.

В этой статье мы подробно разберем, как обеспечить гарантированное закрытие сессии 1С, даже если сама обработка «забыла» это сделать. Рассмотрим несколько подходов — от создания «обертки» до системного контроля процессов.

Способ 1. Использование универсальной обработки-загрузчика

Проанализируем наиболее надежный способ, предложенный в обсуждении. Суть метода заключается в том, чтобы запускать не целевую обработку напрямую, а специальную вспомогательную обработку (лоадер), которая возьмет на себя управление жизненным циклом программы.

Разберем алгоритм работы такой «запускалки»:

  1. Мы передаем путь к целевой обработке через параметр командной строки /C.
  2. Загрузчик считывает этот путь, программно подключает обработку и запускает её выполнение.
  3. После завершения работы (успешного или с ошибкой) загрузчик сам вызывает команду закрытия системы.

Пример кода для такой обработки-загрузчика (в модуле формы или в процедуре ПриОткрытии):


Процедура ПриОткрытии()
    ПутьКЦелевойОбработке = ПараметрЗапуска;
    
    Если ЗначениеЗаполнено(ПутьКЦелевойОбработке) Тогда
        Попытка
            // Подключаем внешнюю обработку программно
            ОбъектОбработки = ВнешниеОбработки.Создать(ПутьКЦелевойОбработке, Ложь);
            // Вызываем экспортный метод или открываем форму
            ОбъектОбработки.ВыполнитьКоманду(); 
        Исключение
            ЗаписьЖурналаРегистрации("ОшибкаЗапуска", УровеньЖурналаРегистрации.Ошибка, , , 
                "Не удалось выполнить обработку: " + ОписаниеОшибки());
        КонецПопытки;
    КонецЕсли;

    // Гарантированное завершение работы системы
    ЗавершитьРаботуСистемы(Ложь);
КонецПроцедуры

Командная строка для запуска в этом случае будет выглядеть так:

"C:\Program Files\1cv8\bin\1cv8.exe" ENTERPRISE /S"Server/Base" /N"Admin" /Execute "C:\Scripts\Загрузчик.epf" /C "C:\Scripts\ЦелеваяОбработка.epf"

Способ 2. Использование COM-соединения (V83.Application)

Если мы хотим полностью контролировать процесс извне, рассмотрим вариант использования COM-объекта. В этом случае мы не просто запускаем исполняемый файл, а создаем экземпляр приложения 1С, которым можем управлять из скрипта (например, на VBScript или PowerShell).

Выясним преимущества этого метода: вызывающий скрипт «знает», когда метод обработки завершился, и может принудительно уничтожить объект приложения. Рассмотрим пример логики на языке VBScript:


Set v83 = CreateObject("V83.Application")
res = v83.Connect("Srvr=""server"";Ref=""base"";Usr=""admin"";Pwd=""123"";")

If res Then
    Set epf = v83.ExternalDataProcessors.Create("C:\Scripts\Work.epf")
    epf.ExecuteYourMethod() ' Вызов вашего метода
    v83.Exit(False)
End If

Важный момент: При использовании V83.Application запускается полноценное клиентское приложение. Если выполнение кода внутри 1С прервется ошибкой или модальным окном, скрипт может «повиснуть». Чтобы этого избежать, в современных скриптах на PowerShell можно добавить проверку таймаута.

Способ 3. Контроль процесса через PowerShell

Посмотрим на ситуацию со стороны операционной системы. Если мы не хотим менять код 1С, мы можем ограничить время жизни процесса 1cv8.exe. Проанализируем пример скрипта PowerShell, который запускает 1С, ждет определенное время и, если программа не закрылась сама, принудительно завершает её.


$process = Start-Process "C:\Program Files\1cv8\8.3.x\bin\1cv8.exe" -ArgumentList "ENTERPRISE /S'Server/Base' /Execute 'C:\test.epf'" -PassThru

# Ждем завершения 10 минут (600 секунд)
if ($process.WaitForExit(600000)) {
    Write-Host "1С завершилась штатно с кодом " $process.ExitCode
} else {
    Write-Host "Превышено время ожидания. Принудительное завершение..."
    Stop-Process -Id $process.Id -Force
}

Этот способ является наиболее «грубым», но самым надежным против зависаний из-за забытых команд закрытия или непредвиденных диалоговых окон.

Способ 4. Подавление диалоговых окон

Часто 1С не закрывается не потому, что нет команды ЗавершитьРаботуСистемы(), а потому, что перед закрытием или во время работы возникло модальное окно. Например: «Конфигурация базы данных изменена», «Подтвердите легальность» или вопрос о завершении работы.

Для минимизации таких рисков при программном запуске обязательно используйте дополнительные ключи командной строки:

Способ 5. Использование глобального параметра запуска

Если у вас есть возможность вносить изменения в конфигурацию, можно реализовать универсальный механизм в модуле управляемого приложения. Разберем, как это работает через процедуру ПриНачалеРаботыСистемы.

В коде модуля пропишем логику:


Процедура ПриНачалеРаботыСистемы()
    Если Найти(ПараметрЗапуска, "AutoExit") > 0 Тогда
        // Если в параметре запуска есть флаг автовыхода, 
        // планируем завершение после всех обработчиков ожидания
        ПодключитьОбработчикОжидания("ПринудительноЗавершитьРаботу", 1, Истина);
    КонецЕсли;
КонецПроцедуры

Процедура ПринудительноЗавершитьРаботу() Экспорт
    ЗавершитьРаботуСистемы(Ложь);
КонецПроцедуры

Теперь при запуске 1С с ключом /C "AutoExit" система сама закроется сразу после инициализации и выполнения базовых действий, если только внешняя обработка не перехватит управление.

Подведем итог: Самым гибким решением для разработчика является Способ 1 (Обработка-загрузчик). Он позволяет централизованно управлять логикой запуска любых внешних файлов, вести лог ошибок и гарантировать вызов ЗавершитьРаботуСистемы() независимо от того, какой код написан внутри целевой обработки.

← На главную