Проблема «зависших» сеансов или пользователей, которые оставляют программу открытой на всю ночь, актуальна для многих организаций. Это не только занимает лицензии, но и создает риски безопасности, а также может мешать проведению регламентных работ (например, обновлению конфигурации или созданию архивных копий). В рамках данной статьи мы подробно разберем, как программно и административно определить отсутствие активности и корректно завершить работу приложения.
Прежде чем приступать к написанию сложного кода, проанализируем возможности, которые предоставляет сама платформа 1С:Предприятие. В консоли администрирования кластера серверов или в параметрах информационной базы существуют настройки, позволяющие управлять «спящими» сеансами. Рассмотрим их подробнее.
Для настройки через конфигуратор или в режиме «1С:Предприятие» (если это предусмотрено интерфейсом администрирования) используются следующие параметры:
Важно понимать принцип работы: сеанс считается пассивным, если от него не поступает запросов к серверу 1С. Если пользователь просто открыл справочник и читает данные, не нажимая кнопок, вызывающих серверные процедуры, система рано или поздно сочтет его пассивным. Однако этот метод лучше всего работает в веб-клиенте. В тонком клиенте настройки часто требуют дополнительного контроля на стороне ОС.
Если нам нужно более гибкое решение, работающее на стороне клиента, мы можем использовать механизм обработчиков ожидания. Разберем алгоритм реализации такого «таймера бездействия» в модуле управляемого приложения.
Основная идея заключается в том, чтобы периодически проверять состояние открытых окон программы. Рассмотрим пример кода, который инициализирует проверку при запуске системы:
Процедура ПриНачалеРаботыСистемы()
// Устанавливаем интервал проверки, например, раз в 5 минут (300 секунд)
ПодключитьОбработчикОжидания("ПроверитьАктивностьПользователя", 300);
КонецПроцедуры
Теперь проанализируем, как определить, изменилось ли что-то в работе пользователя. Один из предложенных на форуме методов — вычисление хеша или простое сравнение текущего состава и заголовков открытых окон. Если в течение нескольких проверок список окон и их заголовки не меняются, мы можем предположить, что пользователь не активен.
Перем ПредыдущийСписокОкон;
Процедура ПроверитьАктивностьПользователя() Экспорт
ТекущиеОкна = ПолучитьОкна();
СтрокаЗаголовков = "";
Для Каждого Окно Из ТекущиеОкна Цикл
СтрокаЗаголовков = СтрокаЗаголовков + Окно.Заголовок + ";";
КонецЦикла;
Если СтрокаЗаголовков = ПредыдущийСписокОкон Тогда
// Пользователь ничего не менял, окна те же.
// Здесь можно наращивать счетчик бездействия.
ЗавершитьРаботуСистемы(Ложь); // Пример немедленного закрытия
Иначе
ПредыдущийСписокОкон = СтрокаЗаголовков;
КонецЕсли;
КонецПроцедуры
Важный нюанс: этот метод имеет погрешность. Если пользователь медленно изучает длинный отчет, прокручивая его мышкой, заголовок окна не меняется, и система может ошибочно закрыть 1С. Поэтому рекомендуется перед закрытием выводить предупреждающее сообщение с таймером обратного отсчета.
Чтобы избежать внезапной потери данных, проанализируем ситуацию, когда система просит пользователя подтвердить свою активность. Это наиболее «дружелюбный» по отношению к пользователю способ.
В обработчике ожидания вместо немедленного закрытия мы можем открывать небольшую форму с вопросом: «Вы еще здесь?». Если пользователь не нажимает кнопку «Да» в течение минуты, вызывается процедура ЗавершитьРаботуСистемы().
Пример логики для такой формы:
Для наиболее точного определения бездействия профессионалы рекомендуют использовать функции операционной системы. В Windows существует функция GetLastInputInfo, которая возвращает время последнего ввода (нажатие клавиши или движение мыши) во всей системе.
Поскольку напрямую вызвать WinAPI из кода 1С нельзя, рассмотрим путь использования внешней компоненты. Выясним преимущества этого метода:
В коде 1С работа с такой компонентой будет выглядеть примерно так:
Попытка
ПодключитьВнешнююКомпоненту("ОбщийМакет.КомпонентаWinAPI", "WinAPI", ТипВнешнейКомпоненты.Native);
ОбъектAPI = Новый("AddIn.WinAPI.Informer");
ВремяБездействия = ОбъектAPI.ПолучитьВремяБездействияВСекундах();
Если ВремяБездействия > 1800 Тогда // 30 минут
ЗавершитьРаботуСистемы(Ложь);
КонецЕсли;
Исключение
// Обработка ошибки подключения компоненты
КонецПопытки
Один из главных рисков — потеря несохраненных данных. Если у пользователя открыта форма документа в режиме редактирования, при вызове ЗавершитьРаботуСистемы() 1С может выдать стандартный запрос «Данные были изменены. Сохранить?». Если пользователя нет на месте, этот вопрос заблокирует закрытие приложения навсегда.
Проанализируем способы решения этой проблемы:
ЭтаФорма.Модифицированность = Ложь. Это приведет к закрытию без вопросов, но данные будут потеряны.Записать() для всех модифицированных форм. Однако это опасно, так как данные могут быть заполнены некорректно.ЗапрашиватьВозможностьЗавершения = Ложь позволяет игнорировать некоторые стандартные проверки, но не всегда обходит проверку модифицированности форм.Подводя итог, можно сказать, что выбор метода зависит от ваших технических возможностей и требований бизнеса. Если в компании используется терминальный доступ (RDP), проще всего настроить таймауты завершения сессий на уровне сервера Windows. Это самый надежный способ очистки ресурсов.
Если же работа идет в локальной сети и нужно именно закрытие приложения 1С, оптимальным будет сочетание обработчика ожидания в модуле управляемого приложения и внешней компоненты для проверки системного времени бездействия. Это позволит избежать ложных срабатываний и обеспечит корректное освобождение лицензий.
Рассмотренные нами методы позволяют гибко настроить политику работы с сеансами, обеспечивая баланс между удобством пользователей и эффективным использованием ресурсов системы 1С:Предприятие.