Внешняя DLL и 1С:Предприятие 8.3: от регистрации до первого вызова
Содержание
Подключить DLL в 1С 8.3 можно двумя способами: зарегистрировать её как COM-сервер и создать через Новый COMОбъект("ProgID") или оформить как внешнюю компоненту Native API и подключить методом ПодключитьВнешнююКомпоненту(). Обычную DLL с экспортируемыми функциями платформа напрямую вызвать не умеет. Ей нужна обёртка под один из этих двух интерфейсов.
Отсюда и большинство проблем: библиотека лежит в папке, путь указан верно, а 1С отвечает Недопустимая строка с указанием класса или Тип не определен. Ниже разобрано, как выбрать интерфейс, зарегистрировать библиотеку
с нужной разрядностью, написать код подключения и найти причину, если что-то не заработало.
COM или Native API: какой способ подключения DLL выбрать
Решение зависит от трёх вещей: где будет работать код (клиент или сервер), на какой ОС и есть ли у вас исходники библиотеки.
| Критерий | COM-объект | Внешняя компонента Native API |
|---|---|---|
| ОС | Только Windows | Windows, Linux, macOS (своя сборка под каждую) |
| Регистрация в системе | Обязательна (regsvr32, regasm) | Не нужна, платформа сама распаковывает и загружает |
| Где хранится | На диске каждого компьютера | В макете конфигурации, внешней обработки или расширения |
| Веб-клиент | Нет | Да, через расширение браузера и сборку под него |
| Разработка | Любой язык с поддержкой COM: C++, C#, Delphi | C++ по интерфейсу Native API (IComponentBase) |
| Передача массивов | COMSafeArray | Только через строку (JSON, XML) или двоичные данные |
| Готовые библиотеки | Многие драйверы и SDK уже COM | Нужно писать обёртку |
Практическое правило:
- 🔹 есть готовый COM-сервер от производителя (сканер, ККТ, SDK банка) и только Windows — берите COM;
- 🔹 библиотека ваша, нужен Linux-сервер или веб-клиент — пишите компоненту Native API;
- 🔹 есть только DLL с «голыми» функциями на C — нужна тонкая обёртка. Быстрее всего на C# с COM-видимым классом, переносимее всего на C++ под Native API.
Технология COM в 1С — это «старый» путь, но для разовой интеграции на Windows он остаётся самым коротким. Native API выигрывает, когда базу тиражируют или переносят на Linux.
Регистрация COM-библиотеки в Windows: regsvr32, regasm и разрядность
COM-объект 1С ищет по ProgID в реестре Windows. Если библиотека не зарегистрирована, никакой код её не найдёт.
Классическая COM-DLL (C++, Delphi)
- Скопируйте DLL и все её зависимости в постоянную папку, например
C:\Program Files\MyLib\. Не регистрируйте из «Загрузок» и временных папок. - Запустите командную строку от имени администратора.
- Выполните регистрацию подходящей утилитой:
:: 64-битная DLL на 64-битной Windows
C:\Windows\System32\regsvr32.exe "C:\Program Files\MyLib\MyLib.dll"
:: 32-битная DLL на 64-битной Windows
C:\Windows\SysWOW64\regsvr32.exe "C:\Program Files (x86)\MyLib\MyLib.dll"
:: Отменить регистрацию
C:\Windows\SysWOW64\regsvr32.exe /u "C:\Program Files (x86)\MyLib\MyLib.dll"
Путаница с папками — классика: System32 на 64-битной системе содержит 64-битные утилиты, а SysWOW64 — 32-битные.
.NET-сборка (C#)
Сборку .NET регистрируют не regsvr32, а RegAsm.exe нужной разрядности:
:: для 32-битного клиента 1С
C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe MyLib.dll /codebase /tlb
:: для 64-битного клиента или сервера 1С
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe MyLib.dll /codebase /tlb
В самой сборке класс должен быть видим для COM: атрибуты [ComVisible(true)], фиксированный [Guid("...")] и [ProgId("MyLib.Calc")], публичный конструктор без параметров.
Главное правило разрядности
Разрядность DLL должна совпадать с разрядностью процесса 1С, который её создаёт. 32-битный тонкий клиент не загрузит 64-битную библиотеку, и наоборот. Ошибка при этом выглядит как «класс не зарегистрирован», хотя регистрация прошла успешно.
Проверить разрядность клиента просто: в окне Справка → О программе указано, 32- или 64-разрядная версия запущена. Для сервера смотрите, из какой папки запущен ragent.exe: Program Files или Program Files (x86).
Код подключения DLL в 1С: COMОбъект и ПодключитьВнешнююКомпоненту
Создание COM-объекта
&НаКлиенте
Процедура ВызватьБиблиотеку(Команда)
Попытка
Калькулятор = Новый COMОбъект("MyLib.Calc");
Исключение
Сообщить("Не удалось создать COM-объект: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
Результат = Калькулятор.Сложить(2, 3);
Сообщить("Результат: " + Формат(Результат, "ЧГ=0"));
КонецПроцедуры
Методы и свойства COM-объекта вызываются по именам, которые задал разработчик библиотеки. Регистр букв не важен. Список доступных методов смотрите в документации к DLL или в библиотеке типов (.tlb) через просмотрщик OLE/COM.
Подключение внешней компоненты Native API
Компонента хранится в общем макете с типом «Внешняя компонента» (ZIP-архив с MANIFEST.XML и сборками под разные ОС). Подключение в коде:
&НаСервере
Функция ПолучитьКомпоненту()
Подключено = ПодключитьВнешнююКомпоненту(
"ОбщийМакет.КомпонентаШтрихкод",
"Штрихкод",
ТипВнешнейКомпоненты.Native);
Если Не Подключено Тогда
ВызватьИсключение "Внешняя компонента не подключена";
КонецЕсли;
Возврат Новый("AddIn.Штрихкод.Генератор");
КонецФункции
Схема имени объекта: AddIn.<имя, указанное при подключении>.<имя класса из компоненты>. Имя класса возвращает функция GetClassNames внутри DLL, его даёт разработчик.
ПодключитьВнешнююКомпоненту() не выбрасывает исключение при неудаче, а возвращает Ложь. Проверяйте результат, иначе ошибка всплывёт строкой ниже как Тип не определен (AddIn.Штрихкод.Генератор).
Подключение на клиенте: асинхронные методы
На клиенте компоненту сначала устанавливают на компьютер (один раз), потом подключают. В конфигурациях, где синхронные вызовы запрещены, используйте асинхронные варианты (платформа 8.3.18 и новее):
&НаКлиенте
Асинх Процедура ПодключитьНаКлиенте(Команда)
Место = "ОбщийМакет.КомпонентаШтрихкод";
Подключено = Ждать ПодключитьВнешнююКомпонентуАсинх(Место, "Штрихкод", ТипВнешнейКомпоненты.Native);
Если Не Подключено Тогда
Ждать УстановитьВнешнююКомпонентуАсинх(Место);
Подключено = Ждать ПодключитьВнешнююКомпонентуАсинх(Место, "Штрихкод", ТипВнешнейКомпоненты.Native);
КонецЕсли;
Если Подключено Тогда
Генератор = Новый("AddIn.Штрихкод.Генератор");
Иначе
Сообщить("Компонента не установлена");
КонецЕсли;
КонецПроцедуры
Схема «попробовать подключить → установить → подключить повторно» избавляет пользователя от лишнего диалога установки при каждом запуске.
Внешняя компонента в макете обработки и в расширении
Не всегда можно менять основную конфигурацию. Компоненту можно положить в макет внешней обработки или расширения.
Внешняя обработка (.epf)
У внешней обработки нет общих макетов, путь вида ОбщийМакет.Имя не сработает. Рабочий приём — поместить макет во временное хранилище и подключать по адресу:
&НаСервере
Функция АдресКомпоненты()
Обработка = РеквизитФормыВЗначение("Объект");
Возврат ПоместитьВоВременноеХранилище(Обработка.ПолучитьМакет("Компонента"), УникальныйИдентификатор);
КонецФункции
&НаКлиенте
Асинх Процедура Подключить(Команда)
Адрес = АдресКомпоненты();
Подключено = Ждать ПодключитьВнешнююКомпонентуАсинх(Адрес, "Штрихкод", ТипВнешнейКомпоненты.Native);
// далее как в основной конфигурации
КонецПроцедуры
Макет в обработке создаётся с типом «Двоичные данные» и содержит тот же ZIP-архив компоненты.
Расширение конфигурации
В расширении (доступны с платформы 8.3.6) добавьте собственный общий макет с компонентой. Обращение к нему такое же: "ОбщийМакет.ИмяМакетаВРасширении". Основная конфигурация при этом не меняется, обновления типовой встают без конфликтов.
Если расширение или обработка работает в безопасном режиме, подключение внешних компонент и создание COM-объектов будет запрещено. Нужно снять флаг безопасного режима у расширения или разрешить компоненты в профиле безопасности. Делайте это только для кода, которому доверяете.
Передача данных между 1С и DLL: типы, массивы, события
Как преобразуются типы
| Тип 1С | COM | Native API |
|---|---|---|
| Число | VT_I4, VT_R8 (целое или дробное) | int32, double |
| Строка | BSTR | WCHAR_T* (UTF-16) |
| Булево | VT_BOOL | bool |
| Дата | VT_DATE | структура tm |
| ДвоичныеДанные | массив байтов | pstrVal с длиной (blob) |
| Массив | COMSafeArray | не передаётся, только сериализацией |
Для Native API строки и двоичные данные, которые компонента возвращает в 1С, нужно выделять через менеджер памяти платформы (IMemoryManager::AllocMemory). Обычный new или malloc приводит к утечкам или падению клиента.
Массивы через COMSafeArray
Параметры = Новый COMSafeArray("VT_VARIANT", 3);
Параметры.SetValue(0, "Склад");
Параметры.SetValue(1, 150);
Параметры.SetValue(2, Истина);
Ответ = Объект.ОбработатьПакет(Параметры);
// Если DLL вернула SafeArray — переводим в массив 1С
МассивОтвета = Ответ.Выгрузить();
Индексы SetValue начинаются с нуля, размер задаётся при создании. Метод Выгрузить() превращает COMSafeArray в обычный Массив.
Сложные структуры в Native API
Передавайте их строкой JSON: в 1С собирайте Структуру и сериализуйте через ЗаписатьJSON(), в DLL разбирайте любой библиотекой JSON. Обратно — так же. Это проще и надёжнее, чем десяток свойств компоненты.
Внешние события
Компонента может сама «дёргать» 1С, например, когда сканер считал код. В DLL вызывается ExternalEvent, в форме срабатывает обработчик:
&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)
Если Источник = "Штрихкод" И Событие = "Считан" Тогда
ОбработатьШтрихкод(Данные);
КонецЕсли;
КонецПроцедуры
Подключение DLL на сервере 1С:Предприятия
Код с &НаСервере выполняется в рабочем процессе rphost, а не на компьютере пользователя. Отсюда три отличия.
- Регистрация на каждом рабочем сервере. COM-DLL регистрируется на всех серверах кластера, где может оказаться сеанс. Native-компонента из макета распаковывается сама.
- Разрядность сервера. Сервер 1С обычно 64-битный. Если производитель дал только 32-битную COM-DLL, есть приём: запустить её вне процесса через суррогат
dllhost.exe. Для этого в разделе реестраHKEY_CLASSES_ROOT\AppID\{GUID класса}создают строковый параметрDllSurrogateс пустым значением, а в разделеCLSID\{GUID}указываютAppID. Тогда 64-битный процесс 1С создаёт объект через COM-маршалинг. - Права учётной записи службы. Служба 1С работает от отдельного пользователя (часто
USR1CV8). Ему нужны права на чтение папки с DLL, а для внешнего COM-сервера — разрешения запуска и активации вdcomcnfg.
На Linux-сервере COM нет вообще. Работает только Native API со сборкой .so в архиве компоненты.
Если компонента упадёт с исключением внутри DLL, вместе с ней упадёт рабочий процесс сервера и оборвутся сеансы пользователей на этом процессе. Тестируйте новую компоненту на копии базы и отдельном сервере, а не в рабочем кластере в разгар дня.
С платформы 8.3.21 у ПодключитьВнешнююКомпоненту есть параметр типа подключения: компоненту можно запустить изолированно, в отдельном процессе. Сбой DLL тогда не роняет основной процесс 1С. Для новых и непроверенных компонент это разумный выбор.
Почему DLL не подключается: диагностика и логирование
Начните с текста ошибки: по нему почти всегда видно, на каком этапе сломалось.
Логирование со стороны 1С
Каждый вызов DLL оборачивайте в Попытка и пишите подробности в журнал регистрации:
Попытка
Результат = Компонента.Отправить(Данные);
Исключение
ЗаписьЖурналаРегистрации("Интеграция.ВнешняяDLL",
УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение;
КонецПопытки;
Своё имя события упрощает фильтр: в журнале регистрации отбираете по «Интеграция.ВнешняяDLL» и видите только эти сбои.
Логирование со стороны DLL
- 📝 пишите в текстовый лог входные параметры и коды возврата каждого метода;
- 📝 для Native API используйте
AddErrorу интерфейса платформы: сообщение придёт в 1С как обычное исключение с понятным текстом; - 🔍 если DLL не грузится вовсе, запустите Process Monitor от Microsoft с фильтром по имени процесса (
1cv8c.exeилиrphost.exe). СтрокиNAME NOT FOUNDпокажут, какую зависимость система не нашла.