При интеграции оборудования через последовательный интерфейс (COM-порт / RS-232) разработчики часто сталкиваются с устаревшими внешними библиотеками. Одной из распространенных проблем является ситуация, когда внешняя компонента vk_rs232.dll корректно принимает и отправляет сигналы, однако в момент закрытия экранной формы весь рабочий сеанс программы аварийно закрывается с ошибкой нарушения прав доступа к памяти.
Проанализируем технические причины такого поведения платформы, рассмотрим шаги для устранения сбоя в существующем коде, а также разберем надежные альтернативные способы работы с портом и входящими данными.
Сбой при закрытии формы происходит на системном уровне из-за специфики архитектуры старых внешних компонент (созданных по технологии COM AddIn на Delphi или C++):
Access Violation (0xC0000005) и мгновенный краш процесса.Разберем по шагам, как предотвратить падение при использовании исходной библиотеки. Главная задача — принудительно отключить опрос оборудования и освободить память до того, как платформа начнет уничтожать элементы интерфейса.
ПередЗакрытием или ПриЗакрытии добавим явный вызов метода остановки порта.Неопределено.Посмотрим на пример правильного освобождения ресурсов:
&НаКлиенте
Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)
Если ОбъектВК <> Неопределено Тогда
Попытка
// Принудительно закрываем соединение с портом
ОбъектВК.ЗакрытьПорт();
Исключение
// Игнорируем ошибки при закрытии, если порт уже был недоступен
КонецПопытки;
// Разрываем ссылку на объект для корректной очистки памяти
ОбъектВК = Неопределено;
КонецЕсли;
КонецПроцедуры
Если используемая сборка vk_rs232 продолжает аварийно завершать работу даже после явного закрытия, рассмотрим переход на классический компонентный интерфейс Windows, аналогичный mscomm32.ocx или zcomm32.commport. Данные компоненты стабильно управляют дескрипторами операционной системы и позволяют перехватывать входящие байты через события 1С.
Разберем реализацию подключения и чтения через обработчик внешних событий:
&НаКлиенте
Перем ОбъектПорта;
&НаКлиенте
Процедура ИнициализироватьПорт(Команда)
Если ОбъектПорта = Неопределено Тогда
Попытка
ОбъектПорта = Новый COMОбъект("zcomm32.commport");
Исключение
Сообщить("Не удалось загрузить COM-объект работы с портом: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Подключаем процедуру обработки входящего потока данных
ДобавитьОбработчик ОбъектПорта.OnComm, ОбработкаВходящихДанных;
// Задаем параметры подключения
ОбъектПорта.CommPort = 1; // Номер COM-порта
ОбъектПорта.Settings = "9600,N,8,1"; // Скорость, четность, бит данных, стоп-бит
ОбъектПорта.InputMode = 1; // 1 — режим массива байтов, 0 — текстовый режим
Попытка
ОбъектПорта.PortOpen = Истина;
Исключение
ОбъектПорта = Неопределено;
Сообщить("Ошибка открытия порта: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОбработкаВходящихДанных()
// Получаем массив байтов из буфера компоненты
МассивБайтов = ОбъектПорта.Input.Выгрузить();
Если МассивБайтов.Количество() >= 4 Тогда
Сообщить("Получены первые байты: " + Строка(МассивБайтов[0]) + ", " + Строка(МассивБайтов[1]));
КонецЕсли;
// При необходимости отправляем подтверждение обратно в порт
ОбъектПорта.OutPut = "OK";
КонецПроцедуры
При использовании модифицированных или альтернативных библиотек данные из буфера нередко возвращаются в виде строки шестнадцатеричных кодов (например, "03415E42") вместо готовой ASCII-строки. Чтобы преобразовать HEX-строку в осмысленный текст или числовое значение, воспользуемся штатным функционалом платформы 1С 8.3 для работы с двоичными данными.
Рассмотрим пример декодирования HEX-последовательности в строку:
&НаКлиенте
Функция ПреобразоватьHEXВТекст(ВходящаяСтрокаHEX)
// Преобразуем шестнадцатеричное представление в объект ДвоичныеДанные
ДвоичныеДанные = ПолучитьДвоичныеДанныеИзШестнадцатеричнойСтроки(ВходящаяСтрокаHEX);
// Восстанавливаем строку с указанием требуемой кодировки оборудования (ANSI / Windows-1251)
Результат = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанные, КодировкаТекста.ANSI);
Возврат Результат;
КонецФункции
Если же необходимо выполнить побайтовый разбор или перевести отдельный байт из шестнадцатеричной системы в десятичное число, разберем вспомогательную функцию преобразования:
&НаКлиенте
Функция Из16В10(Значение16)
Символы16 = "0123456789ABCDEF";
СтрокаHEX = ВРег(СокрЛП(Значение16));
Результат = 0;
Для Индекс = 1 По СтрДлина(СтрокаHEX) Цикл
Символ = Сред(СтрокаHEX, Индекс, 1);
Позиция = СтрНайти(Символы16, Символ) - 1;
Если Позиция < 0 Тогда
Возврат 0; // Некорректный символ
КонецЕсли;
Результат = Результат * 16 + Позиция;
КонецЦикла;
Возврат Результат;
КонецФункции
При работе с внешними библиотеками COM-портов учитывайте ключевые особенности платформы:
vk_rs232.dll, mscomm32.ocx и их модификации существуют преимущественно в 32-разрядном (x86) исполнении. При запуске 64-разрядного клиента 1С загрузка таких компонент вызовет ошибку инициализации. Для их работы необходимо устанавливать 32-битный дистрибутив платформы.