Как подключить внешнюю компоненту Delphi в 1С 8.3 на клиенте и решить проблему разрядности

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

Разработка и подключение собственных внешних компонент (ВК) для платформы «1С:Предприятие 8.3» — это отличный способ расширить стандартные возможности системы. Часто ВК пишутся на Delphi для интеграции с торговым или промышленным оборудованием, например, для работы с COM-портами, USB-устройствами, весами или сканерами. Однако при первой же попытке запустить скомпилированную библиотеку на стороне клиента разработчики часто сталкиваются с ошибками инициализации.

В этой статье мы подробно разберем, почему возникает ошибка при вызове методов загрузки внешних компонент, как влияет разрядность операционной системы и платформы 1С на этот процесс, а также рассмотрим переход от устаревшей технологии COM к современному стандарту Native API.

Устаревший метод подключения по технологии COM

Рассмотрим классический пример, с которого начинают многие разработчики. Допустим, у нас имеется скомпилированная динамическая библиотека testvk.dll, созданная на Delphi. Традиционный (но устаревший) способ работы с ней в коде 1С выглядит следующим образом:


&НаКлиенте
Процедура КомандаПодключитьВК(Команда)
    ПутьКФайлу = "C:\1\Шаблон ВК\TestVK\DLL\testvk.dll";
    
    // Попытка зарегистрировать и загрузить библиотеку
    Результат = ПодключитьВнешнююКомпоненту(ПутьКФайлу, "AveRomix", ТипВнешнейКомпоненты.COM);
    
    Если Результат Тогда
        Попытка
            ОбъектВК = Новый ("AddIn.AveRomix.TestVK");
            Сообщить("Компонента успешно подключена и объект создан!");
        Исключение
            Сообщить("Ошибка при создании объекта: " + ОписаниеОшибки());
        КонецПопытки;
    Иначе
        Сообщить("Не удалось подключить внешнюю компоненту.");
    КонецЕсли;
КонецПроцедуры

При использовании этого кода функция ПодключитьВнешнююКомпоненту очень часто возвращает Ложь, либо падает с ошибкой на этапе инициализации. Проанализируем ключевые причины такого поведения системы.

Причина сбоя: Конфликт разрядностей (x32 против x64)

Основная проблема, из-за которой внешняя компонента отказывается загружаться, заключается в несовместимости архитектур (разрядностей) исполняемого файла 1С и динамической библиотеки DLL:

  1. Если на компьютере пользователя запущен 64-разрядный клиент 1С (исполняемый файл 1cv8.exe или 1cv8c.exe имеет архитектуру x64), он физически не сможет загрузить в свое адресное пространство 32-разрядную библиотеку testvk.dll.
  2. Старые версии среды разработки, такие как популярная среди инженеров Delphi 7, умеют компилировать код исключительно под 32-битную архитектуру (x86).
  3. Для решения этой проблемы необходимо скомпилировать библиотеку под целевую архитектуру клиента 1С. Если клиент 64-битный, то и DLL обязана быть 64-битной.

Возможность компиляции под x64 появилась в среде Delphi только начиная с версии XE2. Если у вас нет доступа к современным коммерческим версиям Delphi, отличным бесплатным решением станет переход на кроссплатформенную среду Lazarus (FreePascal). Она полностью совместима с синтаксисом Object Pascal и позволяет компилировать библиотеки под любые операционные системы и архитектуры (включая Windows x64 и Linux x86/x64).

Эволюция технологии: Переход от COM к Native API

Использование COM-технологии для внешних компонент накладывает серьезные ограничения:

Современным стандартом разработки для платформы 1С является технология Native API. Она лишена указанных недостатков:

Для быстрой разработки Native API компонент на Delphi или Lazarus рекомендуется использовать готовую бесплатную библиотеку с открытым исходным кодом 1CNativeLib. Она содержит все необходимые обертки интерфейсов сопряжения с 1С, избавляя вас от написания низкоуровневого кода взаимодействия с виртуальной машиной 1С.

Автоматический выбор разрядности с помощью Manifest.xml

Чтобы избавить себя от необходимости вручную проверять разрядность клиента 1С в коде и загружать разные файлы, мы можем использовать встроенный механизм платформы 1С — механизм манифестов. Для этого выполним следующие шаги:

  1. Скомпилируем две версии нашей компоненты: my_vk_x32.dll и my_vk_x64.dll.
  2. Создадим текстовый файл с именем MANIFEST.xml следующего содержания:

<?xml version="1.0" encoding="UTF-8"?>
<bundle xmlns="http://v8.1c.ru/8.2/addin/bundle">
    <component os="Windows" arch="i386" path="my_vk_x32.dll" shared="true"/>
    <component os="Windows" arch="x86_64" path="my_vk_x64.dll" shared="true"/>
</bundle>
  1. Упакуем эти три файла (обе DLL и манифест) в один общий ZIP-архив, например, MyComponent.zip.
  2. Поместим полученный архив в конфигурацию 1С в качестве макета с типом Двоичные данные.

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


&НаКлиенте
Функция ПодключитьНативнуюКомпоненту() Экспорт
    
    ИмяМакета = "Обработка.МояОбработкаОбслуживания.Макет.КомпонентаMyVK";
    ИмяПути = "MyNativeVK";
    
    // Пробуем подключить компоненту из кэша платформы
    Результат = ПодключитьВнешнююКомпоненту(ИмяМакета, ИмяПути, ТипВнешнейКомпоненты.Native);
    
    Если Не Результат Тогда
        // Если не удалось, инициируем установку/обновление компоненты на клиенте
        УстановитьВнешнююКомпоненту(ИмяМакета);
        // Повторяем попытку подключения
        Результат = ПодключитьВнешнююКомпоненту(ИмяМакета, ИмяПути, ТипВнешнейКомпоненты.Native);
    КонецЕсли;
    
    Если Результат Тогда
        Возврат Новый("AddIn.MyNativeVK.Extension"); // "Extension" - имя объекта, заданное внутри ВК
    Иначе
        Сообщить("Ошибка: невозможно загрузить внешнюю компоненту MyVK!");
        Возврат Неопределено;
    КонецЕсли;
    
КонецФункции

Изолированный режим подключения в новых версиях 1С 8.3

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

При использовании метода ПодключитьВнешнююКомпоненту мы можем явно указать этот параметр:


Результат = ПодключитьВнешнююКомпоненту(ИмяМакета, ИмяПути, ТипВнешнейКомпоненты.Native, ТипПодключенияВнешнейКомпоненты.Изолированно);

Преимущество изолированного режима: Если ваша Delphi-компонента совершит критическую ошибку (например, вызовет Access Violation из-за некорректной работы с памятью или сбоя драйвера COM-порта), процесс самого клиента 1С не завершится аварийно. Упадет только изолированный контейнер компоненты. Это повышает общую отказоустойчивость системы автоматизации.

Если же ваша компонента должна взаимодействовать с графическим интерфейсом операционной системы (например, захватывать фокус окон или выводить собственные формы поверх окон 1С), то изолированный режим может блокировать такие действия. В таком случае используйте параметр ТипПодключенияВнешнейКомпоненты.НеИзолированно.

Особенности разработки ВК для работы с COM-портами

Поскольку автор исходного вопроса планирует использовать компоненту для управления исполнительным устройством через виртуальный COM-порт (USB-интерфейс), выделим важные архитектурные рекомендации:


&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)
    Если Источник = "MyNativeVK" Тогда
        ПроанализироватьДанныеОтПорта(Данные);
    КонецЕсли;
КонецПроцедуры

Применение кроссплатформенной среды Lazarus, компиляция библиотек под x32 и x64 архитектуры с использованием манифеста, а также переход на Native API позволят вам создавать быстрые, надежные и безопасные внешние компоненты для любых версий платформы «1С:Предприятие 8.3».

← На главную