Как настроить получение данных из COM-порта в 1С через компоненту MSComm с использованием внешних событий (без обработчика ожидания)

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

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

В этой статье мы подробно разберем, как уйти от постоянного опроса порта и настроить полноценную асинхронную обработку поступающих данных с помощью популярной ActiveX-компоненты MSComm (Microsoft Communications Control) и механизма динамического связывания событий в 1С. Мы детально изучим настройку свойств компоненты, особенности её регистрации в современных 64-битных операционных системах Windows 10/11 и методы обхода лицензионных ограничений.

Суть проблемы и архитектурное решение

Для реализации событийной модели нам необходимо заставить ActiveX-компоненту самостоятельно уведомлять платформу 1С о том, что в буфер COM-порта поступили новые данные. Компонента MSComm имеет штатное событие OnComm, которое генерируется при изменении состояния порта или при получении данных. Наша задача — связать это событие с процедурой-обработчиком на языке 1С.

Связывание событий COM-объекта в 1С выполняется с помощью встроенного метода ДобавитьОбработчик. Это позволяет отказаться от таймеров и обрабатывать данные только в момент их физического появления в порту.

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

Шаг 1. Инициализация и базовая настройка MSComm в 1С

Для того чтобы событие OnComm вызывалось корректно, критически важно настроить внутренние свойства самого COM-объекта сразу после его создания. Проанализируем ключевые свойства компоненты:

  1. CommPort — числовой номер виртуального или физического COM-порта (например, 3 для порта COM3).
  2. Settings — строка параметров подключения (скорость, четность, бит данных, стоповые биты). По умолчанию часто используется "9600,N,8,1".
  3. RThreshold (Receive Threshold) — определяющее свойство для генерации событий. По умолчанию оно равно 0, что означает, что событие OnComm при получении данных вообще **не будет генерироваться**. Чтобы событие срабатывало при получении каждого символа, мы обязаны установить это свойство в значение 1.
  4. InputLen — количество символов, считываемых из буфера за один вызов свойства Input. Установка значения 0 указывает компоненте считывать весь накопившийся буфер целиком.

Посмотрим на пример кода инициализации и настройки порта в модуле управляемой формы 1С:


&НаКлиенте
Перем КомпонентаMSComm;

&НаКлиенте
Процедура ИнициализироватьПодключениеКПорту()

    Попытка
        // Создаем COM-объект MSComm32
        КомпонентаMSComm = Новый COMОбъект("MSCOMMLib.MSComm.1");
        
        // Настраиваем параметры порта
        КомпонентаMSComm.CommPort = 3; // Укажите ваш номер порта
        КомпонентаMSComm.Settings = "9600,N,8,1"; // Скорость и четность
        
        // Важно: настраиваем порог срабатывания события OnComm на 1 символ
        КомпонентаMSComm.RThreshold = 1; 
        
        // Будем считывать весь буфер целиком при обращении к Input
        КомпонентаMSComm.InputLen = 0; 
        
        // Открываем порт
        КомпонентаMSComm.PortOpen = Истина;
        
        // Динамически подключаем обработчик события OnComm к нашей процедуре в 1С
        ДобавитьОбработчик КомпонентаMSComm.OnComm, ОбработчикСобытияOnComm;
        
        Сообщить("COM-порт успешно открыт. Ожидание данных...");
    Исключение
        Сообщить("Не удалось инициализировать COM-порт. Ошибка: " + ОписаниеОшибки());
    КонецПопытки;

КонецПроцедуры

Шаг 2. Разработка процедуры-обработчика события OnComm

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

Текущее состояние события мы можем определить с помощью свойства CommEvent. Значение 2 (константа comEvReceive) означает, что в буфер приема поступило количество символов, равное или превышающее значение свойства RThreshold. Выясним, как правильно отфильтровать нужные нам события и считать данные из порта:


&НаКлиенте
Процедура ОбработчикСобытияOnComm()
    
    // Проверяем причину вызова события через свойство CommEvent
    // Значение 2 означает получение данных (comEvReceive)
    Если КомпонентаMSComm.CommEvent = 2 Тогда
        
        Попытка
            // Считываем данные из буфера компоненты
            ВходящиеДанные = КомпонентаMSComm.Input;
            
            Если ЗначениеЗаполнено(ВходящиеДанные) Тогда
                // Направляем полученную строку на дальнейшую обработку
                ОбработатьПолученныйПакет(ВходящиеДанные);
            КонецЕсли;
        Исключение
            Сообщить("Ошибка при чтении данных из порта: " + ОписаниеОшибки());
        КонецПопытки;
        
    КонецЕсли;
    
КонецПроцедуры

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

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


&НаКлиенте
Процедура ПриЗакрытии(ЗавершениеРаботы)
    
    // Отключаем обработчик и закрываем порт
    Если КомпонентаMSComm <> Неопределено Тогда
        Попытка
            УдалитьОбработчик КомпонентаMSComm.OnComm, ОбработчикСобытияOnComm;
            Если КомпонентаMSComm.PortOpen Тогда
                КомпонентаMSComm.PortOpen = Ложь;
            КонецЕсли;
            КомпонентаMSComm = Неопределено;
        Исключение
            // Подавляем ошибки при закрытии порта
        КонецПопытки;
    КонецЕсли;
    
КонецПроцедуры

Шаг 3. Решение проблемы разрядности (32-бит vs 64-бит) в Windows x64

Библиотека mscomm32.ocx является устаревшим 32-разрядным ActiveX-компонентом. Если ваше клиентское приложение 1С:Предприятие запущено в 64-битном режиме (что стандартно для современных конфигураций 1С на платформе x64), вы получите ошибку инициализации COM-объекта, так как 64-битный процесс 1С не может напрямую загрузить 32-битный внутрипроцессный сервер (DLL/OCX).

Для преодоления этого системного ограничения разберем по шагам схему запуска компоненты в изолированном суррогатном процессе Windows с помощью службы Компоненты COM+ (Component Services):

  1. Скопируйте файл mscomm32.ocx в системную директорию C:\Windows\SysWOW64.
  2. Запустите командную строку от имени Администратора и зарегистрируйте библиотеку командой:
    regsvr32 C:\Windows\SysWOW64\mscomm32.ocx
  3. Откройте утилиту управления ОС: Панель управления -> Администрирование -> Службы компонентов (или выполните команду dcomcnfg).
  4. В дереве консоли перейдите по пути: Службы компонентов -> Компьютеры -> Мой компьютер -> Приложения COM+.
  5. Нажмите правой кнопкой мыши по разделу "Приложения COM+" и выберите Создать -> Приложение.
  6. В мастере создания выберите "Создать новое приложение", укажите имя (например, "MSComm_Wrapper") и выберите способ активации: Библиотека пула (Library application) или Серверное приложение (Server application). Для надежной изоляции процесса x64 рекомендуется выбирать Серверное приложение.
  7. В созданном приложении откройте ветку Компоненты, нажмите правой кнопкой мыши, выберите Создать -> Компонент.
  8. Выберите пункт "Импорт уже зарегистрированных компонентов" и найдите в списке зарегистрированную библиотеку MSCOMMLib.MSComm.1. Завершите настройку мастера.

После этой несложной настройки операционная система Windows будет автоматически запускать 32-битную компоненту в выделенном 32-битном системном процессе-контейнере dllhost.exe, прозрачно транслируя вызовы свойств, методов и событий в 64-битный процесс клиента 1С.

Шаг 4. Решение проблемы лицензирования (Ошибка CLASS_E_NOTLICENSED)

При переносе вашего решения на другие клиентские компьютеры вы гарантированно столкнетесь с системной ошибкой инициализации COM-объекта (код ошибки 80040112 или текст CLASS_E_NOTLICENSED). Данная ошибка возникает из-за того, что библиотека MSComm изначально поставлялась как инструмент среды разработки Visual Basic 6.0 и требует наличия специальной «лицензии разработчика» в системном реестре Windows.

Выясним способ устранения этой проблемы на компьютерах пользователей, где среда разработки Visual Studio или VB6 не установлена. Для этого необходимо вручную или программно импортировать в реестр Windows соответствующую ветку лицензии.

Создайте текстовый файл с расширением .reg (например, mscomm_license.reg) и поместите в него следующее содержимое:


Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Licenses\4250E830-6AC2-11cf-8ADB-00AA00C00905]
@="kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun"

Запустите созданный файл от имени Администратора для внесения изменений в системный реестр. После применения этой записи компонента MSComm станет беспрепятственно инициализироваться на любых рабочих станциях пользователей под управлением Windows 10/11.

Шаг 5. Современные альтернативы MSComm в 1С

Несмотря на то, что использование MSComm позволяет быстро решить задачу асинхронного приема данных, данная технология считается устаревшей и имеет определенные недостатки (зависимость от настроек COM+, необходимость прав администратора для записи реестра, возможная нестабильность при обновлении Windows).

Проанализируем две ключевые современные альтернативы для работы с COM-портом в экосистеме 1С:

  1. Использование библиотеки классов .NET (C#) через COM-обертку:

    Платформа .NET предоставляет современный, надежный и многопоточный класс System.IO.Ports.SerialPort. Используя механизмы динамического взаимодействия с .NET в 1С (например, сторонние CLR-хостинги или компоненты-мосты), можно напрямую получать данные из порта. Класс SerialPort самостоятельно обрабатывает событие получения данных DataReceived в фоновом потоке, что обеспечивает превосходную стабильность работы даже при экстремально высокой частоте передачи данных.

  2. Разработка внешней компоненты по технологии Native API:

    Для крупных промышленных проектов наиболее правильным решением является разработка или приобретение внешней компоненты (ВК) Native API на языке C++ или Rust. Такие компоненты не имеют привязки к COM-технологиям Windows, кроссплатформенны (могут работать на Linux-клиентах), асинхронно слушают порт в фоновом системном потоке и генерируют стандартное для 1С ВнешнееСобытие. При таком подходе перехват данных осуществляется внутри предопределенной платформенной процедуры управляемой формы:

    
    &НаКлиенте
    Процедура ВнешнееСобытие(Источник, Событие, Данные)
        // Обработка сигналов от Native API компоненты
        Если Источник = "МояКомпонентаПорта" Тогда
            ОбработатьШтрихкод(Данные);
        КонецЕсли;
    КонецПроцедуры
    

Подводя итоги нашего детального разбора, отметим, что связывание события OnComm компоненты MSComm посредством встроенного механизма ДобавитьОбработчик — это отличный способ быстро запустить асинхронный обмен с торговым оборудованием в среде Windows без усложнения кодовой базы внешними зависимостями.

← На главную