Как задать вопрос пользователю при закрытии управляемого приложения 1С?

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

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

Почему не работают стандартные функции диалогов при выходе

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

Рассмотрим пример кода, который приводит к ошибке:


Процедура ПередЗавершениемРаботыСистемы(Отказ, ТекстПредупреждения)
    Если Вопрос("Завершить работу?", РежимДиалогаВопрос.ОКОтмена) = КодВозвратаДиалога.Отмена Тогда
        Отказ = Истина;
    КонецЕсли;
КонецПроцедуры

При выполнении такого кода платформа 1С выдает ошибку: «Открытие окон при завершении работы запрещено». Это связано со следующими архитектурными ограничениями:

  1. Блокировка интерфейса: В момент инициализации выхода главное окно и окружение управляемого интерфейса переходят в режим завершения сеанса и деинициализации ресурсов. Открытие новых синхронных модальных окон в этот момент заблокировано платформой.
  2. Отказ от модальности: В современных конфигурациях 1С 8.3 при включенном режиме Режим использования модальности = Не использовать синхронные вызовы Вопрос() и Предупреждение() запрещены на уровне платформы.
  3. Процедура ПриЗавершенииРаботыСистемы не имеет параметров: В данном обработчике отменить завершение программы уже невозможно, так как процесс закрытия запущен безвозвратно.

Штатный способ: использование параметров события ПередЗавершениемРаботыСистемы

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

Разберем параметры данной процедуры:

  1. Отказ (тип Булево) — признак отмены штатного выхода из программы. По умолчанию равен Ложь.
  2. ТекстПредупреждения (тип Строка) — текст, который платформа отобразит в своем встроенном диалоговом окне.

Посмотрим на пример правильной базовой реализации:


Процедура ПередЗавершениемРаботыСистемы(Отказ, ТекстПредупреждения)
    ТекстПредупреждения = "Вы действительно хотите выйти из программы?";
    Отказ = Истина;
КонецПроцедуры

Рассмотрим механизм работы этого кода:

  1. Устанавливая Отказ = Истина, мы сообщаем платформе, что закрытие окна требует интерактивного подтверждения.
  2. Заполняя ТекстПредупреждения, мы передаем текст в системное диалоговое окно платформы.
  3. Платформа самостоятельно выводит стандартный диалог с кнопками подтверждения и отмены. Если пользователь выбирает продолжение работы, программа остается открытой. Если пользователь подтверждает выход, сеанс завершается без повторного вызова обработчика.

Особенность работы в веб-клиенте: При работе через браузер перехват закрытия страницы контролируется механизмом beforeunload. В целях безопасности веб-браузеры могут заменять произвольный текст предупреждения на системное сообщение («Покинуть страницу?» или «Остаться»).

Реализация сложного асинхронного диалога перед закрытием

Если перед выходом требуется не просто стандартный вопрос, а сложный интерактивный сценарий (например, сохранение несохраненных данных или выбор дополнительных параметров), стандартного параметра ТекстПредупреждения может быть недостаточно. В этом случае применяют сценарий с глобальным флагом и асинхронным оповещением.

Разберем по шагам реализацию такого алгоритма в модуле управляемого приложения:


&НаКлиенте
Перем РазрешитьЗакрытие Экспорт;

Процедура ПередЗавершениемРаботыСистемы(Отказ, ТекстПредупреждения)
    
    Если РазрешитьЗакрытие = Истина Тогда
        Возврат;
    КонецЕсли;
    
    // Блокируем текущую попытку закрытия
    Отказ = Истина;
    
    // Вызываем асинхронный диалог
    Оповещение = Новый ОписаниеОповещения("ПослеОтветаНаВопросОЗакрытии", ЭтотОбъект);
    ПоказатьВопрос(Оповещение, "Сохранить изменения перед выходом?", РежимДиалогаВопрос.ДаНетОтмена);
    
КонецПроцедуры

Процедура ПослеОтветаНаВопросОЗакрытии(Результат, ДополнительныеПараметры) Экспорт
    
    Если Результат = КодВозвратаДиалога.Да Тогда
        // Выполняем действия по сохранению данных
        РазрешитьЗакрытие = Истина;
        ЗавершитьРаботуСистемы();
    ИначеЕсли Результат = КодВозвратаДиалога.Нет Тогда
        // Завершаем работу без сохранения
        РазрешитьЗакрытие = Истина;
        ЗавершитьРаботуСистемы();
    КонецЕсли;
    // При выборе "Отмена" ничего не делаем, остаемся в системе
    
КонецПроцедуры

Проанализируем логику этого решения:

  1. При первой попытке закрытия срабатывает ПередЗавершениемРаботыСистемы. Так как флаг РазрешитьЗакрытие не установлен, выход отменяется через Отказ = Истина, и вызывается неблокирующий метод ПоказатьВопрос().
  2. В процедуре оповещения ПослеОтветаНаВопросОЗакрытии обрабатывается выбор пользователя.
  3. Если пользователь подтвердил закрытие, флаг устанавливается в РазрешитьЗакрытие = Истина, и программно вызывается метод ЗавершитьРаботуСистемы().
  4. При повторном входе в ПередЗавершениемРаботыСистемы проверка флага пропускает процедуру без установки отказа, и программа штатно закрывается.

Методы программного завершения работы

В зависимости от сценария платформа 1С предоставляет различные методы закрытия приложения:

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

Для типовых конфигураций на базе Библиотеки стандартных подсистем (БСП) логику перед закрытием рекомендуется встраивать в модуль СтандартныеПодсистемыКлиентПереопределяемый в процедуру ПередЗавершениемРаботыСистемы, что обеспечивает корректное взаимодействие со всеми служебными механизмами конфигурации.

← На главную