Как устранить ошибку «Класс не лицензирован для использования» (0x80040112) при создании COM-объекта MSComm32 в 1С?

Программист 1С v8.3 (Управляемые формы) Промышленность, строительство и АПК
← На главную

При интеграции торгового или производственного оборудования (весов, сканеров, датчиков) через последовательный порт разработчики нередко используют стандартную библиотеку Microsoft MSComm32.ocx. Однако при вызове конструктора Новый COMОбъект("MSCOMMLib.MSComm") на стороне тонкого клиента платформа может выдать исключение: -2147221230(0x80040112): Класс не лицензирован для использования. Разберем, почему возникает эта ошибка, как правильно зарегистрировать библиотеку и какие нюансы следует учесть при работе с COM-портом из 1С.

Анализ причины ошибки 0x80040112

Элемент управления MSComm32.ocx изначально разрабатывался для среды Visual Basic 6.0 и содержит механизм защиты времени разработки (Design-Time License). В отличие от размещения элемента на экранной форме в среде разработки, динамическое создание объекта через конструктор COM требует обязательного наличия специального ключа в системном реестре Windows.

Когда 1С выполняет инициализацию объекта, операционная система проверяет ветку реестра HKEY_CLASSES_ROOT\Licenses. Если нужной записи нет либо у текущего пользователя операционной системы отсутствуют права на чтение данной ветки, вызов завершается кодом ошибки CLASS_E_NOTLICENSED (0x80040112).

Чаще всего с этой проблемой сталкиваются в следующих сценариях:

  1. Регистрация выполнена под другой учетной записью: системный администратор импортировал файл лицензии (.reg) под своей учетной записью локального администратора, а пользователь 1С работает под ограниченной локальной или доменной учетной записью, для которой ключ недоступен.
  2. Разрядность операционной системы: на 64-битных версиях Windows для 32-разрядных приложений ключ должен находиться в ветке HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Classes\Licenses.
  3. Несоответствие разрядности клиента 1С: библиотека MSComm32.ocx существует только в 32-битном исполнении. Если запущен 64-разрядный тонкий клиент 1С (1cv8c.exe x64), создание COM-объекта завершится неудачей.

Пошаговое решение проблемы с лицензированием

Выясним, как устранить ошибку на клиентском рабочем месте:

  1. Убедимся в разрядности клиента: проверьте, что тонкий клиент 1С запущен в 32-разрядном режиме (x86).
  2. Определим текущего пользователя ОС: если вход в 1С выполняется под терминальной сессией или под служебной записью, уточните точное имя пользователя и компьютера с помощью функций ИмяКомпьютера() и ИмяПользователяОС().
  3. Внесем ключ лицензии для всех пользователей: лицензионный ключ должен быть добавлен в реестр таким образом, чтобы доступ к нему имели все профили операционной системы. Для этого ключ вносится в ветку HKEY_LOCAL_MACHINE (включая узел WOW6432Node для x64 систем), либо регистрационный .reg-файл запускается непосредственно из-под сеанса того пользователя, который работает в 1С.
  4. Проверим серверный контекст: если код выполняется строго в директиве &НаКлиенте, регистрировать компоненту на сервере «1С:Предприятия» не требуется. Регистрация через regsvr32 и внесение лицензии нужны только на клиентской машине, к которой физически подключены весы.

Ошибки в коде опроса COM-порта и способы их исправления

Посмотрим на типовой пример опроса весов, в котором создается COM-объект и считываются данные:


&НаКлиенте
Процедура Брутто(Команда)
    Попытка
        Весы = Новый COMОбъект("MSCOMMLib.MSComm");
    Исключение
        Сообщить("Ошибка создания объекта MSCommLib: " + ОписаниеОшибки(), СтатусСообщения.Внимание);
        Возврат;
    КонецПопытки;
    
    Весы.CommPort = 7;
    Весы.Settings = "9600,N,8,1";
    Весы.InputLen = 0;
    
    Попытка
        Весы.PortOpen = 1; 
    Исключение
        Сообщить("Порт занят другим устройством или недоступен.");
        Возврат;
    КонецПопытки;
    
    тЗапросНаВзвешивание = Символ(2) + "AB03" + Символ(3);
    
    Для Н = 1 По 5 Цикл
        Весы.Output = тЗапросНаВзвешивание;
        
        // Потенциально опасный участок: бесконечное ожидание
        Пока Весы.InBufferCount < 12 Цикл
            #Если Клиент Тогда
                ОбработкаПрерыванияПользователя();
            #КонецЕсли
        КонецЦикла;
        
        См = Весы.Input;
        // Дальнейший парсинг строки...
    КонецЦикла;
    
    Весы.PortOpen = 0;
КонецПроцедуры

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

  1. Зависание клиентского потока: цикл Пока Весы.InBufferCount < 12 Цикл ожидает поступления строго 12 байт. Если весы отключены, выключено питание или произошел сбой интерфейса, программа намертво зависнет с загрузкой процессорного ядра на 100%. Метод ОбработкаПрерыванияПользователя() не защищает от зависания интерфейса при отсутствии реакции оператора. Обязательно должен быть реализован счетчик таймаута.
  2. Блокировка порта в системе: закрытие порта Весы.PortOpen = 0 расположено в самом конце процедуры. Если при разборе строки (например, при вызове функции Число()) возникнет ошибка, выполнение прервется, а порт останется монопольно захваченным процессом 1С. Все последующие попытки взвешивания будут завершаться ошибкой.

Оптимизированный и безопасный вариант чтения данных

Перепишем алгоритм так, чтобы гарантировать освобождение порта и предотвратить зависание программы:


&НаКлиенте
Процедура ПолучитьВесБезопасно(Команда)
    Попытка
        Весы = Новый COMОбъект("MSCOMMLib.MSComm");
    Исключение
        Сообщить("Не удалось инициализировать MSComm: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;
    
    Весы.CommPort = 7;
    Весы.Settings = "9600,N,8,1";
    Весы.InputLen = 0;
    
    Попытка
        Весы.PortOpen = 1;
    Исключение
        Сообщить("Не удалось открыть COM-порт. Проверьте подключение устройства.");
        Возврат;
    КонецПопытки;
    
    ЗнСВесов = 0;
    тЗапрос = Символ(2) + "AB03" + Символ(3);
    
    Попытка
        Для ПопыткаОпроса = 1 По 5 Цикл
            Весы.Output = тЗапрос;
            
            // Защита от зависания: ограничиваем максимальное число итераций ожидания
            ИтерацийОжидания = 0;
            Пока Весы.InBufferCount < 12 И ИтерацийОжидания < 50000 Цикл
                ИтерацийОжидания = ИтерацийОжидания + 1;
                #Если Клиент Тогда
                    ОбработкаПрерыванияПользователя();
                #КонецЕсли
            КонецЦикла;
            
            Если Весы.InBufferCount >= 12 Тогда
                Ответ = Весы.Input;
                Ответ = СтрЗаменить(Ответ, Символ(3), "");
                Ответ = Сред(СтрЗаменить(Ответ, Лев(тЗапрос, 3), ""), 2);
                Ответ = Лев(Ответ, СтрДлина(Ответ) - 2);
                
                ЗнСВесов = Число(Ответ);
                Прервать;
            КонецЕсли;
        КонецЦикла;
    Исключение
        Сообщить("Ошибка при чтении данных с весов: " + ОписаниеОшибки());
    КонецПопытки;
    
    // Гарантированное закрытие порта
    Если Весы.PortOpen = 1 Тогда
        Весы.PortOpen = 0;
    КонецЕсли;
    
    Если ЗнСВесов > 0 Тогда
        Объект.Брутто = ЗнСВесов;
        Объект.РучнойВводБрутто = Ложь;
        Объект.ДатаПолученияБрутто = ТекущаяДата();
    КонецЕсли;
КонецПроцедуры

Современные альтернативы MSComm32.ocx

Использование устаревших COM-компонент времен Visual Basic 6.0 влечет за собой сложности с лицензированием, несовместимость с 64-битными клиентами и невозможность работы на ОС Linux. Рекомендуется рассмотреть более надежные решения:

  1. 1С:Библиотека подключаемого оборудования (БПО): использование стандартных обработчиков БПО и сертифицированных драйверов весов. Механизм работает штатно, поддерживает асинхронные события и исключает зависание интерфейса.
  2. Внешние компоненты Native API: компоненты для работы с последовательными портами, собранные по технологии Native API, поддерживают кроссплатформенность (Windows/Linux), обе разрядности (x86 и x64), загружаются прямо из макета конфигурации без прав администратора и не зависят от записей в реестре.
← На главную