Как организовать обработчик событий COM-объекта на сервере 1С

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

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

Анализ проблемы: почему ДобавитьОбработчик не работает на сервере

Для начала разберем техническую причину. Когда мы используем команду ДобавитьОбработчик для COM-объекта в тонком или толстом клиенте, 1С задействует механизмы Windows Message Loop (петля сообщений). COM-объект, генерируя событие, отправляет уведомление в поток приложения, который находится в состоянии ожидания. Процесс rphost (рабочий процесс сервера 1С), в отличие от клиентского приложения, работает в неинтерактивном режиме как сервис. У него нет «окна» и классической петли сообщений, которая необходима для интерфейсов типа IConnectionPoint.

Кроме того, серверные потоки в 1С являются частью пула потоков. Они могут динамически создаваться и уничтожаться. Если вы создадите COM-объект в фоновом задании и подпишетесь на события, поток может завершить свою работу сразу после выполнения кода, не дождавшись самого события. Даже если организовать бесконечный цикл ожидания, серверный контекст просто «не услышит» входящий RPC-вызов от COM-сервера.

Проанализируем ситуацию: автору задачи требуется реакция в реальном времени даже при отсутствии активных пользователей. Это означает, что нам нужно решение, работающее 24/7. Рассмотрим основные стратегии реализации такой задачи.

Решение №1: Использование «клиента-робота»

Это самый простой в реализации метод, который не требует написания кода на сторонних языках программирования. Разберем его по шагам:

  1. Выделяем отдельную учетную запись пользователя в 1С (например, Robot_COM_Listener).
  2. На сервере (или выделенной виртуальной машине) настраиваем автоматический запуск тонкого клиента под этой учетной записью при старте системы.
  3. В модуле управляемого приложения или в специальной обработке прописываем инициализацию COM-объекта и установку обработчика событий.

Пример кода для клиентского приложения:


// В модуле управляемого приложения или обработки
Перем МойCOMОбъект;

Процедура ПриНачалеРаботыСистемы()
    #Если ТонкийКлиент Или ТолстыйКлиентОбычноеПриложение Тогда
        МойCOMОбъект = Новый COMОбъект("ExternalSoftware.Application");
        ДобавитьОбработчик МойCOMОбъект.OnNewData, ОбработкаСобытияНовыхДанных;
    #КонецЕсли
КонецПроцедуры

Процедура ОбработкаСобытияНовыхДанных(Данные)
    // Здесь мы можем вызвать серверный метод для записи в регистр
    ЗаписатьСобытиеНаСервере(Данные);
КонецПроцедуры

Важный момент: Для обеспечения отказоустойчивости рекомендуется использовать планировщик задач Windows, который будет проверять, запущен ли процесс 1cv8c.exe, и перезапускать его в случае падения. Это решение превращает клиентское приложение в своего рода «сервисный процесс».

Решение №2: Промежуточная веб-прокладка (HTTP-сервисы)

Если мы хотим избежать запуска лишних клиентских сеансов 1С, нам потребуется создать внешнее приложение-посредник. Рассмотрим архитектуру этого решения: стороннее ПО генерирует событие -> «прокладка» ловит событие -> «прокладка» отправляет HTTP-запрос в 1С.

Выясним причину, почему это надежнее: внешний процесс (написанный на C#, Python или даже в виде скрипта PowerShell) имеет собственную петлю сообщений и может работать как полноценная служба Windows. Он не зависит от сеансов 1С и может буферизировать данные, если сервер 1С временно недоступен.

В самой 1С нам необходимо создать HTTP-сервис с методом POST. Разберем примерную структуру метода в 1С:


Функция ОбработатьСобытие(Запрос)
    Тело = Запрос.ПолучитьТелоКакСтроку();
    // Логика парсинга данных (например, из JSON)
    ДанныеJSON = ПрочитатьJSONДанные(Тело);
    
    МенеджерЗаписи = РегистрыСведений.ИсторияСобытий.СоздатьМенеджерЗаписи();
    МенеджерЗаписи.Период = ТекущаяДата();
    МенеджерЗаписи.Событие = ДанныеJSON.EventName;
    МенеджерЗаписи.Значение = ДанныеJSON.Value;
    МенеджерЗаписи.Записать();
    
    Возврат Новый HTTPСервисОтвет(200);
КонецФункции

Решение №3: Скрипт PowerShell как служба

Посмотрим на пример реализации «прокладки» с помощью PowerShell. Это мощный инструмент, который отлично взаимодействует с COM-объектами и позволяет отправлять HTTP-запросы без компиляции сложного ПО.

Проанализируем пример скрипта:


$comObject = New-Object -ComObject "ExternalSoftware.Application"
$eventCode = {
    param($sender, $eventArgs)
    $data = @{
        EventName = "DataReceived"
        Value = $sender.LastValue
    } | ConvertTo-Json
    
    Invoke-RestMethod -Uri "http://myserver/base/hs/events/v1" -Method Post -Body $data
}

Register-ObjectEvent -InputObject $comObject -EventName "OnNewData" -Action $eventCode

while($true) { Start-Sleep -Seconds 1 } # Удержание скрипта в памяти

Этот скрипт можно обернуть в службу Windows с помощью утилиты nssm или аналогичных средств. Это гарантирует, что обработка событий будет идти в фоновом режиме 24/7 без участия пользователя.

Решение №4: Настройка DCOM и прав доступа

При переносе логики взаимодействия с COM на сторону сервера, мы неизбежно столкнемся с проблемами прав доступа. Выясним, что нужно настроить, чтобы сервер 1С мог работать с объектом.

Сервер 1С обычно запускается под технической учетной записью (например, USR1CV8). По умолчанию у этой записи нет прав на запуск и активацию многих COM-серверов. Разберем шаги по настройке:

  1. Запустите dcomcnfg (Службы компонентов).
  2. Найдите нужный COM-объект в ветке «Настройка DCOM».
  3. В свойствах на вкладке Безопасность добавьте пользователя USR1CV8 в разделы «Разрешения на запуск и активацию» и «Разрешения на доступ».
  4. На вкладке Удостоверение (Identity) вместо «Интерактивный пользователь» лучше выбрать «Указанный пользователь» и ввести данные учетной записи, под которой ПО точно работает корректно. Это критично, так как на сервере нет интерактивной сессии.

Сравнение подходов и выводы

Рассмотрим, какой метод выбрать в зависимости от условий:

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

← На главную