При выполнении административных процедур, таких как обновление конфигурации, реструктуризация таблиц или создание архивной копии, возникает необходимость завершить работу всех активных пользователей. В файловом варианте базы достаточно закрыть приложение, однако в клиент-серверном варианте (SQL) сеансы удерживаются кластером серверов 1С:Предприятия.
Разберем, почему возникает ошибка при попытке завершить соединения через обычное COM-подключение, как правильно управлять процессами сервера программно и какие существуют альтернативные способы решения этой задачи.
Рассмотрим типовой сценарий, с которого часто начинаются попытки написать обработку для сброса сеансов. Разработчик создает объект V82.COMConnector (или V83.COMConnector) и вызывает метод Connect() с обычной строкой подключения к информационной базе. После этого вызывается метод Сервер.Disconnect(Соединение), приводящий к ошибке:
Метод объекта не обнаружен (Disconnect)
Выясним причину такого поведения. Метод Connect() возвращает внешнее соединение к самой информационной базе (аналог объекта информационной базы, в котором доступны менеджеры справочников, документов и функций конфигурации). Однако методы управления физическими соединениями и сессиями принадлежат не контексту базы данных, а уровню администрирования кластера серверов 1С (рабочему процессу или агенту сервера). Следовательно, обычное соединение с базой просто не содержит метода Disconnect.
Посмотрим на рабочий вариант кода, предложенный автором после исправления структуры вызова. Для прямого управления соединениями базы мы можем подключиться к конкретному рабочему процессу через метод ConnectWorkingProcess.
Разберем по шагам алгоритм работы с рабочим процессом:
V83.COMConnector.ConnectWorkingProcess.AddAuthentication.CreateInfoBaseInfo и указываем ее имя в кластере.GetIBConnections.Disconnect.
Процедура ЗавершитьСоединенияБазы()
Коннектор = Новый COMОбъект("V83.COMConnector");
Попытка
// Подключаемся к рабочему процессу (порт процесса может отличаться)
Сервер = Коннектор.ConnectWorkingProcess("tcp://SQL:1641");
// Аутентификация администратора нужной информационной базы
Сервер.AddAuthentication("Администратор", "ПарольАдмина");
// Описание целевой базы
ИнформационнаяБаза = Сервер.CreateInfoBaseInfo();
ИнформационнаяБаза.Name = "WorkBase";
// Получение активных соединений
СоединенияБазы = Сервер.GetIBConnections(ИнформационнаяБаза);
// Завершение каждого соединения
Для Каждого Соединение Из СоединенияБазы Цикл
Сервер.Disconnect(Соединение);
КонецЦикла;
Исключение
Сообщить("Ошибка отключения: " + ОписаниеОшибки());
КонецПопытки;
Коннектор = Неопределено;
КонецПроцедуры
Важное замечание: В платформе 1С:Предприятие 8.3 рабочие процессы используют пул динамических портов (по умолчанию из диапазона 1560–1591). Сеансы одной и той же информационной базы могут быть распределены по разным рабочим процессам, а при жестком указании порта (например, 1641) можно получить доступ только к части пользователей.
Проанализируем ключевое архитектурное отличие между соединениями и сеансами в 1С:Предприятии 8.3:
Если разорвать только сетевое соединение методом Disconnect, тонкий клиент или толстый клиент при включенном механизме восстановления связи может заново установить сетевой контакт в рамках того же незавершенного сеанса. Пользователь при этом даже не покинет программу.
Чтобы гарантированно выгнать пользователя, необходимо удалять именно сеанс, вызывая метод TerminateSession у агента кластера. Рассмотрим правильный код подключения к главному агенту сервера (порт 1540):
Процедура ЗавершитьСеансыЧерезАгента()
СерверАдрес = "SQL";
ПортАгента = "1540";
ИмяБазы = "WorkBase";
Коннектор = Новый COMОбъект("V83.COMConnector");
Попытка
// Подключаемся к агенту сервера
Агент = Коннектор.ConnectAgent(СерверАдрес + ":" + ПортАгента);
Кластеры = Агент.GetClusters();
Для Каждого Кластер Из Кластеры Цикл
// Аутентифицируемся в кластере
Агент.Authenticate(Кластер, "АдминистраторКластера", "ПарольКластера");
// Получаем список всех сеансов кластера
Сеансы = Агент.GetSessions(Кластер);
Для Каждого ТекСеанс Из Сеансы Цикл
// Отбираем сеансы только нашей информационной базы
Если НСтр(ТекСеанс.InfoBase.Name) = НСтр(ИмяБазы) Тогда
// Исключаем собственный текущий сеанс при необходимости
// Завершаем сеанс на уровне кластера
Агент.TerminateSession(Кластер, ТекСеанс);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Исключение
Сообщить("Ошибка при работе с сеансами: " + ОписаниеОшибки());
КонецПопытки;
Коннектор = Неопределено;
КонецПроцедуры
При использовании технологии COM важно помнить о технических ограничениях платформы:
COMОбъект (32-битный или 64-битный клиент/сервер 1С), должна совпадать с разрядностью зарегистрированной в операционной системе библиотеки comcntr.dll.Для универсального и кроссплатформенного администрирования фирма «1С» рекомендует использовать сервер администрирования ras и консольную утилиту rac. Этот подход работает одинаково стабильно на Windows и Linux.
Для отключения сеанса через командную строку (которую можно запустить из кода через ЗапуститьПриложение) используется команда:
rac session terminate --cluster=<ID_Кластера> --session=<ID_Сеанса>
Если нет желания работать напрямую с кластером, рассмотрим стандартные средства конфигураций 1С. В типовых конфигурациях (на базе Библиотеки стандартных подсистем) присутствует механизм блокировки работы пользователей.
В типовых конфигурациях доступна стандартная обработка Блокировка работы пользователей (или форма «Активные пользователи» с возможностью принудительного завершения сеансов).
При установке блокировки начала сеансов на уровне кластера или через свойства базы программно важно учитывать два параметра:
SessionsDenied = True запрещает вход обычным пользователям.ScheduledJobsDenied = True предотвращает запуск фоновых задач, которые могут помешать монопольным операциям.PermissionCode). Это позволяет администратору подключаться к заблокированной базе из командной строки с ключом /UC <КодРазрешения>.Автоматическое завершение пассивных и спящих пользователей также можно настроить прямо в свойствах кластера, определив параметры Время засыпания пассивных сеансов и Время завершения спящих сеансов.