Принудительное отключение пользователей 1С из кода: COM, rac и встроенный язык

· 9 мин

Содержание

Программно завершить сеанс пользователя в 1С:Предприятии можно только через администрирование кластера серверов: подключиться к агенту сервера через V83.COMConnector (метод ConnectAgent), найти нужный сеанс и вызвать TerminateSession. Второй путь — утилита rac и сервер администрирования RAS: команда rac session terminate. Платформа не даёт метода «закрыть чужой сеанс» прямо во встроенном языке, поэтому любое решение так или иначе идёт через кластер.

Для файловой базы кластера нет. Там чужой сеанс снаружи не закрыть, работает только «мягкий» приём: сеанс сам проверяет флаг и завершает себя. Его тоже разберём, он пригодится и в клиент-серверном варианте.

Как устроено управление сеансами в кластере 1С

Каждое подключение к клиент-серверной базе — это сеанс в кластере. Сеансом считается не только окно пользователя, но и Конфигуратор, фоновое задание, COM-соединение, обращение к веб-сервису.

Цепочка такая:

  • 🖥️ Агент сервера (ragent, порт 1540) — точка входа. Через него работают консоль кластера и COM-администрирование.
  • 🗂️ Менеджер кластера (rmngr, порт 1541) — хранит список баз и сеансов.
  • ⚙️ Рабочие процессы (rphost) — выполняют код. Диапазон их портов задаётся в свойствах рабочего сервера.
  • 🔌 Сервер администрирования RAS (по умолчанию порт 1545) — отдельная служба, через которую работает утилита rac.

Программа-администратор подключается к агенту (или к RAS), проходит аутентификацию администратора кластера, получает список сеансов и отправляет команду на разрыв. Пользователь, чей сеанс завершён, при следующем обращении к серверу получает сообщение об ошибке и окно с предложением перезапуска. Лицензия, которую занимал сеанс, освобождается.

Какой способ выбрать

СпособГде работаетКогда удобенОграничения
COM (V83.COMConnector)Windowsкод на 1С, скрипты PowerShell и Python на Windowsнужна регистрация comcntr.dll нужной разрядности
rac + RASWindows и Linuxпланировщик, bat/sh, CIнужна запущенная служба RAS
Встроенные средства БСПвнутри типовой конфигурацииадминистратор работает из интерфейсанужны права и параметры кластера
Самозавершение по флагулюбая база, в том числе файловаявежливо выгнать всех перед обслуживаниемне закроет зависший клиент

Подготовка COM-соединения с агентом сервера

COM-объект V83.COMConnector живёт в библиотеке comcntr.dll из каталога bin платформы. Установщик регистрирует её, если при установке отмечен компонент «Сервер 1С:Предприятия» или «Администрирование сервера 1С:Предприятия». Если компонент не ставили, регистрируйте вручную.

  1. Откройте командную строку от имени администратора.
  2. Выполните регистрацию для той версии платформы, что совпадает с версией кластера:
regsvr32 "C:\Program Files\1cv8\<версия>\bin\comcntr.dll"
  1. Проверьте разрядность. 64-битный процесс (PowerShell по умолчанию, 64-битный сервер 1С) видит только 64-битную библиотеку из C:\Program Files. 32-битный клиент — только из C:\Program Files (x86).

Версия comcntr.dll должна совпадать с версией сервера до последней цифры. Если на машине несколько платформ, регистрируется последняя, для которой выполнили regsvr32. После обновления сервера регистрацию повторяют.

Если код на 1С выполняется на сервере (в серверной процедуре), COM-объект создаётся на машине с рабочим процессом и от имени учётной записи службы 1С (обычно USR1CV8). Значит, comcntr.dll регистрируют именно там, а не на компьютере пользователя.

Ещё понадобится логин и пароль администратора кластера. Если администраторы кластера не заведены, аутентификация проходит с пустыми строками. Создайте отдельного администратора для скриптов — так видно в логах, кто отключал людей.

Как найти нужный сеанс: фильтр по базе, пользователю и приложению

Метод GetSessions(Кластер) возвращает все сеансы кластера, по всем базам. Отбирать нужные приходится самому. Полезные свойства объекта сеанса:

СвойствоЧто содержит
SessionIDномер сеанса в базе (тот же, что показывает консоль)
UserNameимя пользователя 1С
AppIDтип приложения
Hostимя компьютера клиента
StartedAtвремя начала сеанса
infoBase.Nameимя базы в кластере

Типичные значения AppID:

  • 1CV8C — тонкий клиент;
  • 1CV8 — толстый клиент;
  • WebClient — веб-клиент;
  • Designer — Конфигуратор;
  • BackgroundJob — фоновое задание;
  • COMConnection — внешнее COM-подключение.

💡 Если баз в кластере много, удобнее сначала получить список баз через GetInfoBases(Кластер), найти нужную по Name, а затем вызвать GetInfoBaseSessions(Кластер, База). Так не придётся перебирать сеансы чужих баз.

Обязательно исключайте свой сеанс. Номер текущего сеанса возвращает функция НомерСеансаИнформационнойБазы(), его сравнивают с SessionID. Иначе скрипт, запущенный из той же базы, отключит сам себя на середине цикла.

Фоновые задания лучше не трогать без нужды: обрыв обмена или закрытия месяца на полпути оставит незавершённую операцию.

Код принудительного завершения сеанса через COM

Ниже рабочая серверная функция на встроенном языке. Она отключает все сеансы указанного пользователя в указанной базе, кроме текущего сеанса и фоновых заданий, и возвращает число завершённых сеансов.

&НаСервереБезКонтекста
Функция ЗавершитьСеансыПользователя(ИмяБазы, ИмяПользователя, АдминКластера = "", ПарольАдмина = "")

    Коннектор = Новый COMОбъект("V83.COMConnector");
    Агент = Коннектор.ConnectAgent("tcp://srv1c:1540");

    ТекущийНомер = НомерСеансаИнформационнойБазы();
    Завершено = 0;

    Для Каждого Кластер Из Агент.GetClusters() Цикл

        Агент.Authenticate(Кластер, АдминКластера, ПарольАдмина);

        Для Каждого Сеанс Из Агент.GetSessions(Кластер) Цикл

            Если НРег(Сеанс.infoBase.Name) <> НРег(ИмяБазы) Тогда
                Продолжить;
            КонецЕсли;

            Если НРег(Сеанс.UserName) <> НРег(ИмяПользователя) Тогда
                Продолжить;
            КонецЕсли;

            Если Сеанс.SessionID = ТекущийНомер
                Или Сеанс.AppID = "BackgroundJob" Тогда
                Продолжить;
            КонецЕсли;

            Попытка
                Агент.TerminateSession(Кластер, Сеанс);
                Завершено = Завершено + 1;
            Исключение
                ЗаписьЖурналаРегистрации("Администрирование.ЗавершениеСеанса",
                    УровеньЖурналаРегистрации.Ошибка, , ,
                    СтрШаблон("Сеанс %1: %2",
                        Формат(Сеанс.SessionID, "ЧГ=0"),
                        ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())));
            КонецПопытки;

        КонецЦикла;

    КонецЦикла;

    Возврат Завершено;

КонецФункции

Что учесть при переносе в свою базу:

  1. Вместо srv1c укажите имя центрального сервера кластера. Если агент слушает не 1540, допишите порт.
  2. Пароль администратора кластера не храните в коде. Держите его в защищённом хранилище или константе с ограниченным доступом.
  3. Вызывать функцию стоит под пользователем с полными правами: создание COM-объекта на сервере требует, чтобы безопасный режим был выключен.

Тот же алгоритм на Python через pywin32 — удобно для планировщика Windows:

import win32com.client

conn = win32com.client.Dispatch("V83.COMConnector")
agent = conn.ConnectAgent("tcp://srv1c:1540")

for cluster in agent.GetClusters():
    agent.Authenticate(cluster, "admin", "password")
    for s in agent.GetSessions(cluster):
        if s.infoBase.Name.lower() == "buh" and s.AppID != "BackgroundJob":
            print(s.SessionID, s.UserName, s.Host)
            agent.TerminateSession(cluster, s)

Отключённый пользователь теряет всё, что не успел записать. Открытые несохранённые документы пропадут. Перед массовым отключением предупредите людей и делайте это вне рабочего времени.

Завершение сеансов через rac и сервер администрирования RAS

На Linux COM нет, и там основной инструмент — rac. Он же удобен на Windows, когда не хочется возиться с регистрацией библиотек.

Сначала нужна запущенная служба RAS. Для проверки её можно поднять вручную на сервере кластера:

"C:\Program Files\1cv8\<версия>\bin\ras.exe" cluster --port=1545 localhost:1540

Для постоянной работы RAS регистрируют службой Windows или юнитом systemd, чтобы он стартовал вместе с сервером.

Дальше последовательность команд:

rac localhost:1545 cluster list
rac localhost:1545 infobase summary list --cluster=<uuid-кластера>
rac localhost:1545 session list --cluster=<uuid-кластера> --infobase=<uuid-базы>
rac localhost:1545 session terminate --cluster=<uuid-кластера> --session=<uuid-сеанса>
  1. cluster list выдаёт идентификатор кластера в поле cluster.
  2. infobase summary list — идентификаторы баз и их имена.
  3. session list показывает сеансы с полями session, user-name, app-id, host.
  4. session terminate разрывает выбранный сеанс.

Если в кластере заведены администраторы, к каждой команде добавляют --cluster-user=<имя> и --cluster-pwd=<пароль>. Остальные параметры смотрите в справке rac help session.

💡 В rac сеанс задаётся UUID, а не номером, который видно в консоли. Номер выводится в поле session-id, UUID — в поле session. Путать их — частая причина ошибки «сеанс не найден».

Для автоматизации вывод session list разбирают построчно: блоки сеансов разделены пустой строкой, поля идут в формате имя : значение. В PowerShell или bash это десяток строк. Затем по каждому подходящему UUID вызывают session terminate.

Встроенные средства конфигурации и HTTP-сервис

Типовые конфигурации на БСП

В БП 3.0, ЗУП 3.1, УТ 11 и других конфигурациях на Библиотеке стандартных подсистем уже есть готовый механизм. Откройте Администрирование → Обслуживание, найдите список активных пользователей. В нём можно выделить сеанс и завершить его командой из формы.

Там же настраивается блокировка работы пользователей: программа запрещает новые входы, рассылает предупреждение и через заданное время отключает оставшиеся сеансы. Для клиент-серверной базы при этом спрашиваются параметры администрирования кластера.

В коде за этим стоит общий модуль АдминистрированиеКластераКлиентСервер. Его функция УдалитьСеансыИнформационнойБазы принимает параметры администрирования кластера, параметры базы и фильтр сеансов. Внутри модуль сам выбирает COM или RAS — по тому, какой тип подключения указан в параметрах. Если ваша конфигурация на БСП, пишите через этот модуль, а не через сырой COM: меньше кода и одинаковое поведение на Windows и Linux.

Мягкое завершение: сеанс закрывает себя сам

Приём для файловых баз и для вежливого отключения перед обслуживанием:

  1. Заведите константу-флаг, например ЗапретитьРаботу, и текст сообщения.
  2. В модуле управляемого приложения при запуске подключите обработчик ожидания с интервалом 60–120 секунд.
  3. Обработчик вызывает серверную функцию, читающую флаг. Если флаг взведён, показывается предупреждение, а через минуту выполняется ЗавершитьРаботуСистемы(Ложь).

Параметр Ложь отключает вопрос о закрытии, и программа закрывается без участия пользователя. Минус приёма в том, что зависший клиент или сеанс без интерфейса (COM-подключение, фоновое задание) флаг не проверит. Их добивают уже через кластер.

HTTP-сервис для внешних систем

Если отключать пользователей нужно из портала, бота или системы мониторинга, оформите HTTP-сервис:

  • 🌐 в конфигурации создайте HTTP-сервис с шаблоном вроде /sessions/{user} и методом DELETE;
  • 🔐 в обработчике проверьте токен из заголовка запроса;
  • ⚙️ вызовите функцию из раздела про COM или УдалитьСеансыИнформационнойБазы из БСП;
  • 📤 верните JSON с количеством завершённых сеансов.

Опубликуйте сервис на веб-сервере через публикацию базы. Обработчик выполняется на сервере 1С, поэтому все требования к comcntr.dll и правам службы те же. Сам HTTP-запрос тоже создаёт сеанс с отдельным AppID — исключайте его фильтром, иначе сервис может отключить сам себя.

Перед отключением пользователей
Выполнено: 0 / 5

Ошибки при отключении сеансов и журналирование

Диагностика: выберите симптом

Журнал нужен по двум причинам: разбирать жалобы «меня выкинуло» и видеть, что скрипт не падает молча. Что записывать по каждому отключённому сеансу:

  • 👤 имя пользователя и компьютер (UserName, Host);
  • 🔢 номер сеанса и тип приложения;
  • 🕐 время начала сеанса и время отключения;
  • ❌ текст ошибки, если TerminateSession не сработал.

Из кода на 1С пишите в журнал регистрации через ЗаписьЖурналаРегистрации с отдельным именем события, как в примере выше. Тогда в журнале регистрации легко отобрать только эти записи. Внешние скрипты пусть пишут в текстовый лог или отправляют итог в мессенджер.

Ещё два правила, которые экономят разбор инцидентов:

  • оборачивайте каждый TerminateSession в Попытка: один «залипший» сеанс не должен останавливать весь цикл;
  • после цикла запросите список сеансов повторно и запишите, сколько осталось. Если сеанс не закрылся, повторный вызов обычно срабатывает.

Частые вопросы

Можно ли завершить чужой сеанс в файловой базе?
Снаружи нет: у файловой базы нет кластера. Работает только самозавершение по флагу через обработчик ожидания или закрытие процесса 1cv8 на компьютере пользователя.
Освобождается ли лицензия после TerminateSession?
Да. Лицензию держит сеанс, после его завершения она возвращается в пул и доступна для нового входа.
Нужны ли права администратора кластера, если администраторы не заданы?
Нет. Если в кластере нет ни одного администратора, Authenticate проходит с пустыми логином и паролем. Это удобно, но небезопасно для рабочего сервера.
Чем завершение сеанса отличается от разрыва соединения?
Разрыв соединения в консоли кластера отключает клиента от рабочего процесса, но сеанс может остаться и восстановиться. Завершение сеанса удаляет его целиком вместе с занятой лицензией.
Можно ли отключить пользователя из внешней обработки?
Да. Код из примера работает и во внешней обработке, если она открыта в базе без безопасного режима и под пользователем с полными правами.