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