Как использовать библиотеку ZeroMQ (NetMQ) в 1С: решение проблем с регистрацией и вызовом методов

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

В современной разработке на платформе 1С часто возникает необходимость интеграции с внешним оборудованием или сторонними сервисами, использующими высокопроизводительные протоколы обмена данными. Одним из таких инструментов является ZeroMQ — асинхронная библиотека обмена сообщениями. Однако при попытке подключить её реализацию для .NET (библиотеку NetMQ) программисты 1С часто сталкиваются с ошибкой «Класс не зарегистрирован». В этой статье мы подробно разберем, почему стандартные методы регистрации COM-объектов не работают и как правильно организовать взаимодействие с ZeroMQ из среды 1С.

Почему возникает ошибка «Класс не зарегистрирован»

Рассмотрим стандартную ситуацию: разработчик скачивает сборку NetMQ.dll, пытается зарегистрировать её через утилиту RegAsm.exe и ожидает, что после этого станет доступна команда Новый COMОбъект("NetMQ"). Проанализируем, почему этот подход ошибочен. Библиотека NetMQ написана на языке C# и является «чистой» .NET-сборкой. Для того чтобы объект этой библиотеки можно было создать как COMОбъект, разработчик библиотеки должен был специально пометить классы атрибутом [ComVisible(true)] и присвоить им уникальные идентификаторы (GUID). В официальной поставке NetMQ этого нет.

Регистрация через RegAsm без соответствующих атрибутов внутри кода библиотеки не делает типы видимыми для механизмов COM, которые использует 1С. Именно поэтому система выдает ошибку о том, что класс не зарегистрирован, даже если утилита PowerShell отрапортовала об успехе.

Решение 1: Использование компоненты NetObjectToIDispatch

Самым эффективным и проверенным способом работы с внешними .NET библиотеками в 1С является использование универсальной «прокладки» — компоненты NetObjectToIDispatch45. Эта компонента выступает в роли моста: она сама является COM-видимой и умеет загружать любые .NET-сборки, используя механизм рефлексии (Reflection).

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


// Создаем объект-враппер для доступа к .NET
Посредник = Новый COMОбъект("NetObjectToIDispatch45");

// Загружаем сборку NetMQ. Важно указать полный путь к файлу
ПутьКБиблиотеке = "C:\NetMQ_Libs\NetMQ.dll";
NetMQСборка = Посредник.ЗагрузитьСборку(ПутьКБиблиотеке);

Важный нюанс, который часто упускают: библиотека NetMQ.dll имеет зависимость от другой библиотеки — AsyncIO.dll. Выясним причину возможных сбоев на этом этапе: если AsyncIO.dll отсутствует в той же папке, что и основной файл, вызов методов будет возвращать ошибки. Убедитесь, что обе библиотеки лежат рядом.

Решение 2: Правильное создание объектов и вызов методов

Проанализируем типичную ошибку при работе с NetObjectToIDispatch. Часто разработчики пытаются получить тип интерфейса, например INetMQSocket, и вызвать у него метод Connect. Однако интерфейс — это лишь описание контракта, создать его экземпляр напрямую нельзя. Выясним, как нужно действовать в архитектуре ZeroMQ.

В NetMQ для разных паттернов обмена используются разные классы сокетов. Если вам нужно отправить запрос и получить ответ (как в случае с JSON-строкой для аппарата), следует использовать RequestSocket. Рассмотрим правильный пример инициализации соединения:


// Получаем тип конкретного класса, а не интерфейса
ТипСокета = Посредник.ПолучитьТип("NetMQ.Sockets.RequestSocket", ПутьКБиблиотеке);

// Создаем экземпляр сокета
Сокет = Посредник.СоздатьОбъект(ТипСокета);

// Теперь метод Connect станет доступен
АдресПодключения = "tcp://192.168.1.100:5555";
Сокет.Connect(АдресПодключения);

В этом примере мы используем tcp транспорт, указывая IP и порт. После успешного вызова Connect объект Сокет будет готов к передаче данных.

Работа с данными: кодировки и JSON

При передаче JSON-строки из 1С в библиотеку NetMQ нужно учитывать разницу в представлении строк. 1С работает со строками в формате Unicode (UTF-16), тогда как большинство устройств, принимающих данные через ZeroMQ, ожидают кодировку UTF-8. Рассмотрим, как отправить данные правильно:

Методы SendFrame или SendReadyString в NetMQ могут принимать как строки, так и массивы байтов. Чтобы избежать проблем с «кракозябрами», рекомендуется использовать встроенные средства 1С для формирования JSON в формате UTF-8 или выполнять конвертацию строк средствами .NET через тот же NetObjectToIDispatch.


// Формируем JSON строку в 1С
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтруктураДанных);
СтрокаJSON = ЗаписьJSON.Закрыть();

// Отправка строки. NetMQ внутри C# обычно корректно маршалит строки, 
// но если аппарат требует строго UTF-8 без BOM, 
// используйте методы отправки байтовых массивов.
Сокет.SendFrame(СтрокаJSON);

Завершение работы и управление ресурсами

ZeroMQ — это библиотека, которая активно использует фоновые потоки. Если просто уничтожить объект в 1С, фоновые процессы могут продолжать работу, что приведет к «зависанию» сеанса 1С в диспетчере задач или блокировке сетевых портов. Проанализируем, как правильно освобождать ресурсы.

Во-первых, у сокета крайне желательно устанавливать параметр Linger. Этот параметр определяет, сколько времени библиотека будет пытаться отправить недоставленные сообщения после закрытия сокета. Для интеграции с оборудованием лучше ставить его в 0.

Во-вторых, необходимо явно вызывать метод закрытия. Посмотрим на правильный цикл завершения:


// Устанавливаем время ожидания закрытия в 0
Сокет.Options.Linger = Посредник.ПолучитьТип("System.TimeSpan").FromSeconds(0);

// Закрываем соединение
Сокет.Close();

// Уничтожаем сокет и освобождаем память
Сокет.Dispose();

Также стоит помнить о статическом классе NetMQConfig. В некоторых сценариях может потребоваться вызов NetMQConfig.Cleanup(), но при использовании через COM-враппер достаточно аккуратного управления объектами сокетов.

Альтернативный вариант: Native API и обертки

Если использование .NET и дополнительных компонент кажется слишком сложным, существует альтернативный путь. Можно использовать нативную библиотеку libzmq.dll (написанную на C++). Для неё можно написать или найти готовую Native API внешнюю компоненту 1С. Преимущество нативного подхода в том, что такая компонента не требует регистрации в реестре (её можно загружать из макета) и она не зависит от установленных версий .NET Framework на компьютере пользователя.

Однако создание такой компоненты требует глубоких знаний C++ или Delphi. Поэтому для большинства задач автоматизации бизнеса использование NetObjectToIDispatch45 совместно с NetMQ.dll остается оптимальным решением по соотношению трудозатрат и результата.

Подведем итоги

Для успешной работы с ZeroMQ в 1С мы выяснили следующие ключевые моменты:

  1. Прямая регистрация NetMQ.dll через RegAsm бесполезна, так как библиотека не является COM-видимой.
  2. Необходимо использовать компоненту-посредник NetObjectToIDispatch45.
  3. Обязательно наличие AsyncIO.dll в одной папке с основной библиотекой.
  4. Для работы нужно создавать объекты конкретных классов (например, RequestSocket), а не пытаться работать с интерфейсами.
  5. Важно следить за кодировкой отправляемых данных и правильно завершать сеанс связи через Close() и Dispose().

Следуя этим рекомендациям, вы сможете построить надежный и быстрый обмен данными между 1С и любым оборудованием, поддерживающим протокол ZeroMQ.

← На главную