При разработке прикладных решений на платформе 1С часто возникает необходимость использовать сторонние системные библиотеки, такие как Scripting.Dictionary, VBScript.RegExp или объекты MS Office. Эти библиотеки не реализуют специализированные интерфейсы 1С (ТСВК), но без проблем создаются через стандартный вызов Новый COMОбъект(). Разберем, как разработать собственный компонент общего назначения, который можно использовать не только в 1С, но и в любых других Windows-приложениях.
Проанализируем ситуацию: для взаимодействия внешнего кода с платформой 1С существуют два принципиально разных подхода:
IInitDone, ILanguageExtender). Такие компоненты подключаются методами ПодключитьВнешнююКомпоненту(), поддерживают генерацию внешних событий в 1С через ВнешнееСобытие и могут инкапсулироваться внутри макетов конфигурации.IDispatch. Создание такого объекта выполняется конструктором Новый COMОбъект("ИмяКласса") (или СоздатьОбъект() в 1С 7.7).Если вам требуется создать универсальный модуль (например, для сложных математических вычислений, интеграции с нестандартным оборудованием или парсинга), достаточно написать классический COM-сервер.
Рассмотрим подробнее технические ограничения и условия, необходимые для корректной работы стороннего COM-объекта в 1С:
IDispatch: Платформа 1С работает с COM-объектами исключительно через механизм позднего связывания (Late Binding). Класс обязан предоставлять интерфейс IDispatch (или Dual-интерфейс). Чистые виртуальные таблицы методов (vtable) платформой не поддерживаются.VARIANT (строки BSTR, целые и вещественные числа, даты VT_DATE, логические значения VT_BOOL, массивы SAFEARRAY или ссылки IDispatch).Для Каждого Элемент Из Коллекция Цикл, объект должен реализовывать скрытый метод _NewEnum с идентификатором DISPID_NEWENUM (значение -4), возвращающий интерфейс IEnumVARIANT.Разберем по шагам создание простого COM-сервера на языке C#. Для обеспечения корректного позднего связывания опишем интерфейс и реализующий его класс с явным указанием GUID:
using System;
using System.Runtime.InteropServices;
namespace MyCustomLib
{
[Guid("364C5E66-4412-48E3-8BD8-7B2BF09E8922")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[ComVisible(true)]
public interface ICalculator
{
int Sum(int a, int b);
string GetVersion();
}
[Guid("8C034F6A-1D3F-4DB8-BC99-B73873D8C297")]
[ProgId("MyCustomLib.Calculator")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class Calculator : ICalculator
{
public int Sum(int a, int b)
{
return a + b;
}
public string GetVersion()
{
return "1.0.0";
}
}
}
Посмотрим на ключевые атрибуты в примере:
[ComVisible(true)] — делает типы видимыми для COM-клиентов.[ProgId("...")] — задает строковый идентификатор класса (ProgID), который будет использоваться в 1С при вызове.[InterfaceType(ComInterfaceType.InterfaceIsDual)] — гарантирует поддержку IDispatch.[ClassInterface(ClassInterfaceType.None)] — отключает автоматическую генерацию интерфейса класса, обязывая использовать явно объявленный контракт ICalculator.Выясним причину, почему собранную библиотеку нужно регистрировать перед вызовом. Windows должна знать, в какой DLL находится запрашиваемый ProgID.
В зависимости от используемой версии платформы .NET регистрация выполняется следующим образом:
regasm MyCustomLib.dll /codebase /tlb..csproj добавьте параметр <EnableComHosting>true</EnableComHosting>. При сборке будет сформирован файл MyCustomLib.comhost.dll, который регистрируется через стандартную системную утилиту Windows: regsvr32 MyCustomLib.comhost.dll.После успешной регистрации библиотеки в операционной системе объект становится доступен в коде 1С. Посмотрим на пример вызова:
Попытка
Калькулятор = Новый COMОбъект("MyCustomLib.Calculator");
Результат = Калькулятор.Sum(15, 27);
Версия = Калькулятор.GetVersion();
Сообщить("Результат сложения: " + Результат);
Сообщить("Версия компоненты: " + Версия);
Исключение
Сообщить("Не удалось создать COM-объект: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;
Проанализируем практические сложности, с которыми можно столкнуться при использовании COM-объектов:
1cv8c.exe) не может загрузить 64-битную COM DLL, и наоборот. Если разрядности сервера 1С или клиента не совпадают с библиотекой, ее следует настроить как серверное приложение в оснастке «Службы компонентов» (DCOM/COM+). В этом случае библиотека исполняется внутри процесса dllhost.exe и доступна из приложений любой разрядности.Новый COMОбъект выполняется в процедуре «НаСервере» или в фоновом задании, убедитесь, что у пользователя операционной системы, под которым работает служба сервера 1С (например, USR1CV8), есть права на чтение ветвей реестра и запуск соответствующей DLL.HTTPСоединение.