Как программно получить список сеансов и завершить их в 1С через COM-соединение?

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

При администрировании серверов 1С:Предприятие часто возникает задача автоматизации управления сеансами пользователей. Например, перед выполнением регламентных работ, обновлением конфигурации или резервным копированием базы данных необходимо корректно «выгнать» активных пользователей и завершить зависшие фоновые задания. Для реализации этой логики разработчики часто используют COM-соединение с агентом сервера 1С. Однако на этом пути можно столкнуться с неочевидными методами API и ошибками проектирования. Для автоматического обслуживания баз без ручного отключения пользователей и контроля процессов по расписанию применяется программа для пакетного обновления и резервного копирования 1С.

В этой статье мы подробно разберем, как правильно подключиться к агенту сервера 1С, как получить список активных сеансов, отфильтровать их по типу запущенного приложения (толстый, тонкий, веб-клиент или фоновое задание) и безопасно завершить их работу.

Разбор типичной ошибки: почему GetAssignmentRules() не подходит для поиска сеансов

Начинающие разработчики при изучении синтакс-помощника иногда путают понятия «требования назначения функциональности» и «приложения, запущенные пользователями». Метод агента сервера GetAssignmentRules() возвращает массив объектов типа ТребованиеНазначенияСервисов.

Выясним причину ошибки: требования назначения функциональности (функциональность Assignment Rules) используются исключительно в КОРП-лицензиях платформы «1С:Предприятие». Они позволяют гибко распределять нагрузку между рабочими серверами в многосерверном кластере (например, выделять отдельный сервер под фоновые задания или под работу определенных баз данных). Если у вас в кластере всего один рабочий сервер или не используются КОРП-лицензии, этот метод всегда будет возвращать пустой массив. Для получения списка работающих пользователей этот метод абсолютно неприменим.

Правильный подход: получение сеансов через GetInfoBaseSessions

Для того чтобы узнать, какие приложения и пользователи сейчас работают с информационной базой, нам необходимо использовать метод GetInfoBaseSessions() у объекта соединения с агентом сервера. Этот метод возвращает коллекцию активных сеансов. Для централизованного мониторинга и контроля подключений через COM-соединение можно воспользоваться конфигурацией для внешнего управления сеансами.

Рассмотрим по шагам и разберем весь процесс построения этого механизма в коде 1С:

  1. Создаем COM-объект V83.COMConnector для связи с сервером.
  2. Подключаемся к агенту локального или удаленного сервера через метод ConnectAgent().
  3. Получаем список кластеров сервера и проходим по ним в цикле (обычно используется первый кластер по индексу 0).
  4. Авторизуемся в кластере (если установлена административная защита кластера).
  5. Находим нужную информационную базу по ее имени в списке баз кластера.
  6. Получаем массив сеансов этой базы с помощью метода GetInfoBaseSessions().

Проанализируем пример кода, реализующий это подключение:


ИмяСервера = "Server1C";
ПортСервера = "1540"; // Стандартный порт агента сервера
ИмяБазы = "Trade_DB";
АдминистраторКластера = "Admin";
ПарольКластера = "P@ssword";

Попытка
    Коннектор = Новый COMОбъект("V83.COMConnector");
    Агент = Коннектор.ConnectAgent(ИмяСервера + ":" + ПортСервера);
Исключение
    ЗаписьЖурналаРегистрации("Администрирование.Подключение", 
        УровеньЖурналаРегистрации.Ошибка, , , 
        "Не удалось создать COM-соединение с агентом сервера: " + ОписаниеОшибки());
    Возврат;
КонецПопытки;

Кластеры = Агент.GetClusters();
Для Каждого Кластер Из Кластеры Цикл
    
    // Проходим авторизацию администратора кластера
    Попытка
        Агент.Authenticate(Кластер, АдминистраторКластера, ПарольКластера);
    Исключение
        Продолжить; // Если авторизация не прошла, пробуем следующий кластер
    КонецПопытки;
    
    // Получаем список информационных баз кластера
    Базы = Агент.GetInfoBases(Кластер);
    ЦелеваяБаза = Неопределено;
    
    Для Каждого База Из Базы Цикл
        Если ВРег(База.Name) = ВРег(ИмяБазы) Тогда
            ЦелеваяБаза = База;
            Прервать;
        КонецЕсли;
    КонецЦикла;
    
    // Если база найдена в текущем кластере, получаем ее сеансы
    Если ЦелеваяБаза <> Неопределено Тогда
        Сеансы = Агент.GetInfoBaseSessions(Кластер, ЦелеваяБаза);
        
        Для Каждого Сеанс Из Сеансы Цикл
            // Здесь мы можем анализировать свойства каждого сеанса
            ИмяПользователя = Сеанс.UserName;
            НомерСеанса = Сеанс.SessionID;
            ИдентификаторПриложения = Сеанс.AppID;
            
            // Логика фильтрации и отключения
        КонецЦикла;
    КонецЕсли;
    
КонецЦикла;

Классификация и фильтрация приложений по свойству AppID

Чтобы реализовать «вариативную реакцию» (например, предупреждать интерактивных пользователей перед отключением, а фоновые задания сбрасывать сразу), необходимо анализировать свойство AppID полученного объекта сеанса. Это свойство возвращает строковый идентификатор клиентского приложения.

Важно: Платформа возвращает строковое значение AppID, которое рекомендуется всегда приводить к нижнему регистру функцией НРег() во избежание ошибок сравнения.

Рассмотрим подробнее полный список основных идентификаторов приложений:

Используя эти идентификаторы, мы можем построить гибкую логику отбора сеансов:


ИдентификаторПриложения = НРег(Сеанс.AppID);

Если ИдентификаторПриложения = "backgroundjob" Или ИдентификаторПриложения = "systembackgroundjob" Тогда
    // Это фоновое задание. Его можно завершить без предупреждения.
    Агент.TerminateSession(Кластер, Сеанс);
ИначеЕсли ИдентификаторПриложения = "1cv8" Или ИдентификаторПриложения = "1cv8c" Или ИдентификаторПриложения = "webclient" Тогда
    // Это интерактивный пользователь. Сначала отправляем предупреждение через ЖР или систему взаимодействия
    // И только по истечении таймаута принудительно завершаем сеанс.
КонецЕсли;

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

Для принудительного разрыва соединения с базой данных используется метод агента сервера TerminateSession(). Ему необходимо передать два параметра: объект кластера и объект конкретного сеанса, полученного из коллекции.

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


Процедура ПринудительноЗавершитьСеансыПользователей(Кластер, База, Агент)
    
    Сеансы = Агент.GetInfoBaseSessions(Кластер, База);
    Для Каждого Сеанс Из Сеансы Цикл
        
        ИдПриложения = НРег(Сеанс.AppID);
        
        // Не закрываем сеансы администратора кластера и конфигураторы, чтобы не прервать собственную работу
        Если ИдПриложения = "designer" Или ИдПриложения = "srvrconsole" Тогда
            Продолжить;
        КонецЕсли;
        
        Попытка
            Агент.TerminateSession(Кластер, Сеанс);
            ЗаписьЖурналаРегистрации("Администрирование.ЗавершениеСеансов", 
                УровеньЖурналаРегистрации.Информация, , , 
                СтрШаблон("Успешно завершен сеанс №%1 (Пользователь: %2, Приложение: %3)", 
                    Сеанс.SessionID, Сеанс.UserName, Сеанс.AppID));
        Исключение
            ЗаписьЖурналаРегистрации("Администрирование.ЗавершениеСеансов", 
                УровеньЖурналаРегистрации.Предупреждение, , , 
                СтрШаблон("Не удалось завершить сеанс №%1: %2", Сеанс.SessionID, ОписаниеОшибки()));
        КонецПопытки;
        
    КонецЦикла;
    
КонецПроцедуры

Риски принудительного удаления фоновых заданий

Важный момент: Бездумное завершение фоновых заданий через метод TerminateSession() несет в себе серьезные инфраструктурные риски. В этот момент транзакция СУБД экстренно обрывается «сверху».

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

  1. Блокировки таблиц: В СУБД (например, MS SQL Server или PostgreSQL) транзакция может уйти в длительный процесс отката (rollback), в ходе которого таблицы останутся заблокированными. Процессы 1С могут «зависнуть» до перезапуска службы сервера.
  2. Неконсистентность данных: Если задание выполняло сложную обработку данных вне единой транзакции (например, поэтапное закрытие месяца, расчет себестоимости, пакетную загрузку из внешних систем), прерывание на середине может оставить базу в частично рассчитанном («битом») состоянии.
  3. Сбои в обменах: Аварийное завершение сеансов интеграции (HTTP, Web-сервисы, распределенные информационные базы) может привести к рассинхронизации данных между информационными системами.

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


// Безопасный способ отмены фонового задания средствами самой конфигурации
Отбор = Новый Структура;
Отбор.Вставить("Состояние", СостояниеФоновогоЗадания.Активно);
АктивныеЗадания = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор);

Для Каждого Задание Из АктивныеЗадания Цикл
    // Проверяем имя метода, чтобы случайно не сбросить системные процессы
    Если Найти(Задание.ИмяМетода, "Синхронизация") > 0 Тогда
        Попытка
            Задание.Отменить();
            ЗаписьЖурналаРегистрации("Администрирование.ФоновыеЗадания", 
                УровеньЖурналаРегистрации.Информация, , , 
                "Отменено фоновое задание: " + Задание.Наименование);
        Исключение
            // Задание могло успеть завершиться самостоятельно за время итерации
        КонецПопытки;
    КонецЕсли;
КонецЦикла;

Современная альтернатива COM: RAS/RAC и БСП

Использование технологии COM (`V83.COMConnector`) сегодня считается устаревающим и нерекомендуемым подходом по следующим причинам:

Решение: Использование утилиты **RAS** (сервер администрирования кластера) и **RAC** (консольный клиент администрирования). Начиная с современных версий Библиотеки стандартных подсистем (БСП), в конфигурациях доступен общий модуль АдминистрированиеКластера. Он позволяет управлять сеансами, отправляя команды через кроссплатформенный сервер администрирования RAS по протоколу TCP/IP.

Рассмотрим по шагам, как завершить сеансы с помощью инструментов БСП без использования COM-объектов:


// Шаг 1: Задаем параметры подключения к серверу администрирования RAS
ПараметрыКластера = АдминистрированиеКластера.ПараметрыАдминистрированияКластера();
ПараметрыКластера.ТипПодключения = "RAS";
ПараметрыКластера.АдресСервераАдминистрирования = "127.0.0.1";
ПараметрыКластера.ПортСервераАдминистрирования = "1545"; // Стандартный порт RAS

ПараметрыИБ = АдминистрированиеКластера.ПараметрыАдминистрированияИнформационнойБазы();
ПараметрыИБ.Имя = "Trade_DB";
ПараметрыИБ.ИмяАдминистратора = "Admin";
ПараметрыИБ.ПарольАдминистратора = "P@ssword";

// Шаг 2: Получаем активные сеансы через БСП
Фильтр = АдминистрированиеКластера.ФильтрСеансов();
Сеансы = АдминистрированиеКластера.СеансыИнформационнойБазы(ПараметрыКластера, ПараметрыИБ, Фильтр);

СписокСеансовКЗавершению = Новый Массив;
Для Каждого Сеанс Из Сеансы Цикл
    // Анализируем свойства сеанса программного интерфейса БСП
    Если Сеанс.ИмяПриложения = "1cv8c" Тогда
        СписокСеансовКЗавершению.Добавить(Сеанс);
    КонецЕсли;
КонецЦикла;

// Шаг 3: Передаем список сеансов на закрытие
Если СписокСеансовКЗавершению.Количество() > 0 Тогда
    АдминистрированиеКластера.ЗавершитьСеансы(ПараметрыКластера, ПараметрыИБ, СписокСеансовКЗавершению);
КонецЕсли;

Данный подход является наиболее стабильным, безопасным и кроссплатформенным для современных конфигураций 1С:Предприятие 8.3.

Новые возможности платформы: Автоматическое отключение сеансов (с версии 8.3.24)

Стоит отметить, что в платформе версии 8.3.24 и выше появился долгожданный встроенный механизм самоочистки «зависших» сеансов.

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

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

← На главную