Внешние компоненты 1С на .NET: работа с типами 1С:ПредприятияВ статье описаны приемы работы с интерфейсом AppDispatch (который позволяет обращаться из ВК к глобальному модулю и данным 1С по технологии OLE Automation), передача параметров ссылочного типа (документы, справочники и т.п.) в/из ВК и приемы предотвращения зависания 1С в памяти. К статье приложен работающий пример тестовой внешней компоненты на VB.NET. | | Автор статьи: romix | Редакторы: Последняя редакция №4 от 18.02.06 | История URL: http://kb.mista.ru/article.php?id=62 | |
Ключевые слова: AppDispatch, OLE, .NET, VB.NET, зависает в памяти, остается в памяти, освобождение памяти, Marshal.Release, Option Strict On disallows late binding, сборщик мусора, ReleaseComObject
Это продолжение статьи
Книга знаний: Написание внешних компонент для 1С на VB.NET и C#
Материал основан на документации 1С «Технология создания внешних компонент», статье с диска ИТС, faq Соарона и собственных экспериментах. Чтобы отыскать требуемые примеры кода, используйте характерные ключевые слова в поисковых системах: AppDispatch, IDispatch, сообщения об ошибках и т.п.
Поправки и дополнения приветствуются.
Обращение к 1С из ВК по OLE Automation
Предположим, что я хочу обратиться из внешней компоненты к справочнику товаров.
Нет проблем:
Dim obj0 As Object
obj0 = obj1C.CreateObject("Справочник.Товары")
obj0.ВыбратьЭлементы()
obj0.ПолучитьЭлемент()
MessageBox.Show("Товар: " + obj0.Наименование)
Не правда ли красиво – свойства и методы написаны по-русски.
Таким же способом можно обращаться к глобальному модулю и вообще делать все, что позволяет делать OLE-доступ к 1С. Необходимо правильно объявить переменную obj1C, о чем написано ниже. Для простоты освоения вы можете сразу загрузить «подопытный» работающий пример, и попытаться проделать с ним несколько экспериментов.
Option Strict On disallows late binding
Однако, чтобы это стало возможным, в свойствах проекта вырубаем «строгий режим» типизации переменных:
OptionStrict = "Off"
Немного подумав, почему VB.NET ругается на «Option Strict On disallows late binding», я заменил эту настройку в файле с расширением .vbproj. Поскольку все настройки теперь хранятся в XML, а мне лениво ползать по меню, я проделал эту настройку текстовым редактором FAR.
Объявление переменной для AppDispatch
Глобальную переменную obj1C я определяю следующим образом:
Dim obj1C As Object
И инициализирую (в методе внешней компоненты) ее так:
obj1C = V7Data.V7Object.AppDispatch
Свойство V7Data.V7Object ранее (в методе Init) определено как
V7Data.V7Object = pConnection
Где pConnection – параметр этого метода (см. образец кода).
Как гласит документация (и подтверждает суровая практика) в методе
Init свойство AppDispatch еще не инициализировано. Это и понятно: 1С должна «как следует» загрузиться, после чего сможет предоставлять различные внешние интерфейсы.
Поэтому я вставляю инициализацию obj1C не в метод Init внешней компоненты, а непосредственно в пользовательский метод:
Case Methods.methTest '//Реализуем метод для тестирования доступа к 1С
If g_flagInit = False Then
obj1C = V7Data.V7Object.AppDispatch
Marshal.Release(Marshal.GetIDispatchForObject(obj1C))
g_flagInit = True
End If
Основной строчкой здесь является
obj1C = V7Data.V7Object.AppDispatch
Это присвоение нашей переменной ссылки на AppDispatch.
Флажок g_flagInit – это просто глобальная булева переменная, которая предотвращает повторную инициализацию obj1C. Вы можете воспользоваться отдельным методом для инициализации, чтобы не иметь дела с глобальными флажками.
Ниже по тексту идет уже непосредственная работа с объектом 1С:
Dim obj0 As Object
obj0 = obj1C.CreateObject("Справочник.Товары")
obj0.ВыбратьЭлементы()
и т.д.
Предотвращение зависания 1С в памяти
Marshal.Release – метод, который уменьшает счетчик ссылок на obj1C (иначе 1С, подобно призраку, зависает в памяти, и снимается только диспетчером задач по Ctrl-Alt-Del – Диспетчер задач, вкладка Процессы...).
В других средах разработки, например, Delphi, требуется колдовать с _AddRef – здесь же колдовство и танцы с бубнами показали единственный рабочий вариант, при котором призрак зависшей (как “Ghost in the Shell”) 1С не норовит остаться в памяти ПК.
Передача агрегатных объектов в ВК
Предположим, что я хочу передавать во внешнюю компоненту не только строки и числа, но и, например, ссылки на элементы справочников. А также получать их же обратно из 1С.
Для тестирования этого режима работы я добавляю во внешнюю компоненту еще несколько методов, которые из кода 1С 7.7 выглядят следующим образом:
//*******************************************
Процедура Выполнить()
net.УстановитьЗначение(ВыбТовары);
зн=net.ПолучитьЗначение();
Сообщить("зн="+зн);
net.Закрыть();
КонецПроцедуры
Значение ВыбТовары – это ссылка на элемент справочника «товары». Я передаю ее в ВК методом net.УстановитьЗначение(ВыбТовары), а затем получаю это же значение из ВК методом зн=net.ПолучитьЗначение();
Вызов net.Закрыть(); я использую, как вы уже, наверное, догадались, для предотвращения зависания 1С в памяти после закрытия. Вот как я реализую эти тестовые методы:
Case Methods.methSetValue
'//Реализуем метод для установки значения из 1С в внешнюю компоненту
g_var = paParams.GetValue(0)
Case Methods.methGetValue
'//Реализуем метод для чтения значения в 1С из внешней компоненты
pvarRetValue = g_var
Case Methods.methClose
'//Реализуем метод для очистки переменной (иначе 1С зависает в памяти)
g_var = Nothing
GC.Collect()
GC.WaitForPendingFinalizers()
Глобальная переменная g_var определена так:
Dim g_var As Object
Или, более строго:
<MarshalAs(UnmanagedType.IDispatch)> Dim g_var As Object
Поскольку наблюдаются проблемы с зависанием 1С в памяти, я очищаю ссылочную переменную g_var, присваивая ей «пустое» значение Nothing, после чего запускаю «сборку мусора»:
GC.Collect()
GC.WaitForPendingFinalizers()
Так сказать, глобальная зачистка территории от призраков.
Способ зачистки, который рекомендует YuriPar
ВК 1С на .NET: призрак OLE-доступа или почему 1С зависает в памяти
10 - 30.12.05 - 11:30
В конце дай Marshal.ReleaseComObject(AppDispatch). Все освободится, Сборщик мусора сам все уберет.
Пример исходного кода внешней компоненты для скачивания:
http://x-romix.narod.ru/vb_OLE.zip
(скачивать ЛЕВОЙ кнопкой мыши, 53К).
Для компиляции примера требуется Visual Studio.NET с установленным VB.NET.
|