При интеграции различного торгового и промышленного оборудования (сканеров штрихкодов, весов, бесконтактных считывателей, датчиков) с платформой 1С:Предприятие разработчики часто сталкиваются с необходимостью работы с COM-портом (RS-232). Традиционный и самый простой подход — использование циклического опроса порта через обработчик ожидания (метод ПодключитьОбработчикОжидания). Однако этот способ сильно нагружает процессор, создает задержки в интерфейсе и не гарантирует мгновенного отклика системы на событие устройства.
В этой статье мы подробно разберем, как уйти от постоянного опроса порта и настроить полноценную асинхронную обработку поступающих данных с помощью популярной ActiveX-компоненты MSComm (Microsoft Communications Control) и механизма динамического связывания событий в 1С. Мы детально изучим настройку свойств компоненты, особенности её регистрации в современных 64-битных операционных системах Windows 10/11 и методы обхода лицензионных ограничений.
Для реализации событийной модели нам необходимо заставить ActiveX-компоненту самостоятельно уведомлять платформу 1С о том, что в буфер COM-порта поступили новые данные. Компонента MSComm имеет штатное событие OnComm, которое генерируется при изменении состояния порта или при получении данных. Наша задача — связать это событие с процедурой-обработчиком на языке 1С.
Связывание событий COM-объекта в 1С выполняется с помощью встроенного метода ДобавитьОбработчик. Это позволяет отказаться от таймеров и обрабатывать данные только в момент их физического появления в порту.
Рассмотрим по шагам, как правильно инициализировать компоненту, настроить её свойства для генерации событий и написать отказоустойчивый код обработчика.
Для того чтобы событие OnComm вызывалось корректно, критически важно настроить внутренние свойства самого COM-объекта сразу после его создания. Проанализируем ключевые свойства компоненты:
CommPort — числовой номер виртуального или физического COM-порта (например, 3 для порта COM3).Settings — строка параметров подключения (скорость, четность, бит данных, стоповые биты). По умолчанию часто используется "9600,N,8,1".RThreshold (Receive Threshold) — определяющее свойство для генерации событий. По умолчанию оно равно 0, что означает, что событие OnComm при получении данных вообще **не будет генерироваться**. Чтобы событие срабатывало при получении каждого символа, мы обязаны установить это свойство в значение 1.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-порт. Ошибка: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Теперь разберем, как должна выглядеть процедура, обрабатывающая входящий поток данных. Событие 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 = Неопределено;
Исключение
// Подавляем ошибки при закрытии порта
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Библиотека mscomm32.ocx является устаревшим 32-разрядным ActiveX-компонентом. Если ваше клиентское приложение 1С:Предприятие запущено в 64-битном режиме (что стандартно для современных конфигураций 1С на платформе x64), вы получите ошибку инициализации COM-объекта, так как 64-битный процесс 1С не может напрямую загрузить 32-битный внутрипроцессный сервер (DLL/OCX).
Для преодоления этого системного ограничения разберем по шагам схему запуска компоненты в изолированном суррогатном процессе Windows с помощью службы Компоненты COM+ (Component Services):
mscomm32.ocx в системную директорию C:\Windows\SysWOW64.regsvr32 C:\Windows\SysWOW64\mscomm32.ocx
dcomcnfg).MSCOMMLib.MSComm.1. Завершите настройку мастера.После этой несложной настройки операционная система Windows будет автоматически запускать 32-битную компоненту в выделенном 32-битном системном процессе-контейнере dllhost.exe, прозрачно транслируя вызовы свойств, методов и событий в 64-битный процесс клиента 1С.
При переносе вашего решения на другие клиентские компьютеры вы гарантированно столкнетесь с системной ошибкой инициализации 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.
Несмотря на то, что использование MSComm позволяет быстро решить задачу асинхронного приема данных, данная технология считается устаревшей и имеет определенные недостатки (зависимость от настроек COM+, необходимость прав администратора для записи реестра, возможная нестабильность при обновлении Windows).
Проанализируем две ключевые современные альтернативы для работы с COM-портом в экосистеме 1С:
Платформа .NET предоставляет современный, надежный и многопоточный класс System.IO.Ports.SerialPort. Используя механизмы динамического взаимодействия с .NET в 1С (например, сторонние CLR-хостинги или компоненты-мосты), можно напрямую получать данные из порта. Класс SerialPort самостоятельно обрабатывает событие получения данных DataReceived в фоновом потоке, что обеспечивает превосходную стабильность работы даже при экстремально высокой частоте передачи данных.
Для крупных промышленных проектов наиболее правильным решением является разработка или приобретение внешней компоненты (ВК) Native API на языке C++ или Rust. Такие компоненты не имеют привязки к COM-технологиям Windows, кроссплатформенны (могут работать на Linux-клиентах), асинхронно слушают порт в фоновом системном потоке и генерируют стандартное для 1С ВнешнееСобытие. При таком подходе перехват данных осуществляется внутри предопределенной платформенной процедуры управляемой формы:
&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)
// Обработка сигналов от Native API компоненты
Если Источник = "МояКомпонентаПорта" Тогда
ОбработатьШтрихкод(Данные);
КонецЕсли;
КонецПроцедуры
Подводя итоги нашего детального разбора, отметим, что связывание события OnComm компоненты MSComm посредством встроенного механизма ДобавитьОбработчик — это отличный способ быстро запустить асинхронный обмен с торговым оборудованием в среде Windows без усложнения кодовой базы внешними зависимостями.