Быстрое создание Внешних Компонент на C#. Примеры использования Глобального Контекста, IAsyncEvent, IExtWndsSupport, WinForms и WPF

15.02.16

Разработка - Разработка внешних компонент

В большинстве случаев хватает и обычного COM объекта, учитывая, что в 8.х можно использовать события. Но иногда нужно использовать Глобальный Контекст для вызова глобальных функций, таких как Сообщить, NewObject и т.д. Кроме того, для использования форм нужен дескриптор окна 1С.
Это продолжение статей
Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент. http://infostart.ru/public/238584/
Там же лежат и исходники

.NET(C#) для 1С. Динамическая компиляция класса обертки для использования .Net событий в 1С через ДобавитьОбработчик или ОбработкаВнешнегоСобытия
http://infostart.ru/public/417830/

1C Messenger для отправки сообщений, файлов и обмена данными между пользователями 1С, вэб страницы, мобильными приложениями а ля Skype, WhatsApp
http://infostart.ru/public/434771/

Использование классов .Net в 1С для новичков
http://infostart.ru/public/448668/

Написанием ВК я занимаюсь давно. Но никогда не писал напрямую.

Я никогда не понимал, зачем нужен IlanguageExtender, когда есть IDispatch.

 

 Давным-давно сделал ВК, которая загружает Объект Автоматизации, поддерживающий ITypeInfo и выполняет все его свойства и методы через IlanguageExtender.

 

Смысл её в том, что пишем обычный  COM класс, но для превращения её в ВК добавляем только один метод  InitFrom1C. Например

 

public void InitFrom1C(object Object1C)

        {

             try

            {

        EventTo1C = Object1C as IAsyncEvent;

 if (SynchronizationContext.Current == null)

       SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());

 

        Sc = SynchronizationContext.Current;

            }

            catch (Exception e)

            {

                MessageBox.Show(e.ToString());

                throw e;

 

            }

        }

И вызов из 1С

 

 

Сообщить(ПодключитьВнешнююКомпоненту("AddIn.AddInFromITypeInfo"));

     РаботаССоккетом  = новый("AddIn.AddInFromITypeInfo");




  //   Соккет=New COMОбъект("ДляОбменаДаннмиЧерезTCP");

 //   РаботаССоккетом.LoadOleObject(Соккет);
     РаботаССоккетом.LoadOleObject("ДляОбменаДаннмиЧерезTCP");
     Если ИспользоватьКПК Тогда
        Попытка
        РаботаССоккетом.ОткрытьАйПиПортСНомеромПорта(ТСПАйПиНомерПорта);
         Исключение
            Сообщить("Нужно подключить новую TCPConnectTo1C.dll");
         РаботаССоккетом.ОткрытьАйПиПорт();
        КонецПопытки;

     Сообщить(РаботаССоккетом.Команда);
     Сообщить(РаботаССоккетом.ДанныеДляКоманды);

   

 

Если в 1С 7.7 через COMОбъект объект нельзя было в параметрах передавать объекты 1С и использовать out и ref параметры, то в восьмерке таких ограничений нет. И можно отказаться от обертки и передавать в Com объект только  объект, передаваемый при вызове Init интерфейса IInitDone

 

public void Init([MarshalAs(UnmanagedType.IDispatch)]

     object connection)

    {

        глобальныйКонтекст = connection;

        Marshal.GetIUnknownForObject(глобальныйКонтекст);

 

    }

 

Вот как это выглядит в 1С

 

    врап=новыйCOMОбъект("NetObjectToIDispatch45");
     Попытка
        //Проверим зарегистрирована ли нужная версия NetObjectToIDispatch45
         тест=НовыйCOMОбъект("AddIn.GlobalContext1C");
         тест=Неопределено;
     Исключение
        ФайлNetObjetToIDispatch45=ЗаписатьМакет("NetObjectToIDispatch","NetObjetToIDispatch45");
         ЗарегистрироватьDLL(ФайлNetObjetToIDispatch45);
     КонецПопытки;


     ФайлТестВК=ЗаписатьМакет("ТестВК");
 
    Если ПодключитьВнешнююКомпоненту("AddIn.GlobalContext1C") Тогда
        объект=Новый ("AddIn.GlobalContext1C");
         ГлобальныйКонтекст=объект.ГлобальныйКонтекст;
         AppDispatch=ГлобальныйКонтекст.AppDispatch;
         AppDispatch.Сообщить("Привет");
         Сообщить(AppDispatch.СтатусСообщения.Важное);
     иначе
        сообщить("Компонента не загружена");
     КонецЕсли;

 



Кроме того, в 1С нельзя лего использовать Глобальный Контекст через AppDispatch

То есть AppDispatch.Сообщить(value)

 

ТипГК = ГК1С.GetType();

App1C = ГК1С.AppDispatch;

 

result = ТипГК.InvokeMember(binder.Name, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, App1C, new object[]{value}););


Для простоты использования я сделал оберку через

DynamicObject


Теперь можно легко использовать

 

public dynamic Новый( paramsobject[] Параметры)

{

 return ГК.NewObject(Параметры);

 }

 public dynamic ПолучитьОписаниеТиповСтроки(int ДлинаСтроки)

 {

 return Новый("ОписаниеТипов", "Строка", null, Новый("КвалификаторыСтроки", ДлинаСтроки, ГК.ДопустимаяДлина.Переменная));

 } // ПолучитьОписаниеТиповСтроки()

 

ГК.Сообщить("Привет из ВК", ГК.СтатусСообщения.Важное);

Вот пример использования ГК и окон

 

Сборка=Врап.ЗагрузитьСборку(ФайлТестВК);
ТестВК=Сборка.GetType("ТестВК.ТестВК");
ТВК=Врап.СоздатьОбъект(ТестВК,ГлобальныйКонтекст);
Сообщить(ТВК.СоздатьОкно());

Использование окон WinForms и в особенности WPF позволяет использовать больший функционала, особенно при применении управляемого приложения.


Стоит отметить, что если для обычного приложения проходил такой код

 

тип=Врап.ПолучитьТипИзСборки("WPFLibrary.Window1",ФайлТестВК);
	Окно=Врап.СоздатьОбъект(тип,ЭтотОбъект,ГлобальныйКонтекст);
	Окно.Show();

То для управляемого приложения он не работает. Ошибка возвращаемого значениея.
Пришлось сделать статческий метод создания окна

 

Window1=Врап.ПолучитьТипИзСборки("WPFLibrary.Window1",ФайлТестВК);
Window1.СоздатьОкно(ЭтаФорма,ГлобальныйКонтекст);


Стоит отметить, что вместо использования ДобавитьОбработчик или ОбработкаВнешненго события

проще дать ссылку на модуль объекта или формы где прописать экспортные функции например

 
 
&НаКлиенте Процедура СообщитьСтр(стр) Экспорт

// Вставить содержимое обработчика. Сообщить(стр);

КонецПроцедуры

И вызывать из кода на C#

Модуль1С.СообщитьСтр(textBox.Text);

 

Ну и добавлю про использование немодального подключения ВК

 

&НаКлиенте
Процедура ПроверитьВК(Команда)
		ProgID="AddIn.GlobalContext1C";

	// Вставить содержимое обработчика.
	 Оповещение = Новый ОписаниеОповещения("УстановитьВК", ЭтотОбъект);
     НачатьПодключениеВнешнейКомпоненты(Оповещение, ProgID);

КонецПроцедуры

&НаКлиенте

Процедура УстановитьВК(Подключено,Параметры) Экспорт
	врап=новый COMОбъект("NetObjectToIDispatch45");

  ProgID="AddIn.GlobalContext1C";
    Попытка
        Вк = Новый (ProgID);
       
	Исключение
		стр=ОписаниеОшибки();
        ПоказатьПредупреждение(, "Компонента  не подключена"+стр);
		 Возврат
   КонецПопытки; 

	        ГК=Вк.ГлобальныйКонтекст;
		AppDispatch=ГК.AppDispatch;
		AppDispatch.Сообщить("Привет");
		Сообщить(AppDispatch.СтатусСообщения.Важное);

КонецПроцедуры
&НаКлиенте


Процедура ПриЗакрытии()
	// Вставить содержимое обработчика.
		ГлобальныйКонтекст=Неопределено;
	Если ТВК<>Неопределено Тогда
		ТВК.Закрыть();
		ТВК=Неопределено;
	КонецЕсли; 	

	
	GC=Врап.ПолучитьТип("System.GC");
	GC.Collect();
	GC.WaitForPendingFinalizers();
	Врап= Неопределено;

КонецПроцедуры
 

Ну и не забывать диспозить объект, содержащий ссылку на Глобальный Контекст, иаче 1С будет висеть в процессах

Внешние Компонеты C# .Net

См. также

Разработка внешних компонент POS терминал Рабочее место Розничная торговля Программист Пользователь Платформа 1С v8.3 1С:Комплексная автоматизация 1.х 1С:Управление торговлей 10 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Розничная и сетевая торговля (FMCG) Рестораны, кафе и фаст-фуд Реклама, PR и маркетинг Управленческий учет Платные (руб)

Медиадисплей покупателя может отображать текущую покупку на кассовом месте, показывать видеорекламу, баннеры, во время простоя разворачивать рекламу на весь экран. Экран можно использовать в качестве графического меню-борда в кафе и видеовывески. В качестве устройства отображения можно использовать Android-планшеты, смарт-телевизоры с Android, мониторы или проекторы под управлением Windows или Linux-компьютера. Linux-версия успешно запускается на одноплатных компьютерах Raspberri Pi и Orange Pi. Настраивается ЛЮБОЙ ДИЗАЙН экрана при помощи встроенного графического редактора! Решение можно масштабировать от одного экрана до тысяч экранов с централизованным управлением.

15000 руб.

30.05.2017    53394    8    69    

45

Разработка внешних компонент Программист Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия 3.0 Платные (руб)

Внешняя компонента позволяет работать c TWAIN-совместимым оборудованием (сканерами, камерами) . Полностью совместима со стандартной TWAIN-компонентой из БСП и может применяться как ее замена без изменения вызовов, при этом может работать с 64-разрядной платформой, а так же имеет расширенную функциональность, например, сохранение результата непосредственно в PDF без использования сторонних утилит. Прекрасно работает на сервере, тонком клиенте и веб-клиенте (проверена работа в браузерах Google Chrome, Mozilla Firefox и Microsoft Internet Explorer).

3000 руб.

12.05.2020    27772    137    98    

89

Разработка внешних компонент Программист Платформа 1С v8.3 Конфигурации 1cv8 Платные (руб)

Внешняя компонента позволяет печатать PDF файлы непосредственно из 1С, не используя при этом сторонних программ. Прекрасно работает на сервере, тонком клиенте и веб-клиенте. Основана на проекте PDFium из состава проекта Chromium/Chrome

1500 руб.

17.09.2018    36224    113    127    

114

Разработка внешних компонент Телефония, SIP Программист Платформа 1С v8.3 Конфигурации 1cv8 Россия Платные (руб)

Внешняя компонента выполнена по технологии Native API для 1С 8.х, обеспечивает доступ к программным АТС Asterisk (FreePBX, Elastix) через AMI интерфейс. Через него можно управлять многими функциями Asterisk (определение номеров, перевод звонков, набор телефона и т. д.)

2400 руб.

04.05.2018    46419    119    66    

64

Разработка внешних компонент Программист Платформа 1С v8.3 Платформа 1C v8.2 Платные (руб)

Внешняя компонента, позволяющая посылать команды и получать ответы по GraphQL протоколу из 1С.Может быть использована при интеграции. В 1С работает на стороне "клиента".

4600 руб.

27.06.2023    3214    2    0    

3

Разработка внешних компонент Программист Платформа 1С v8.3 Конфигурации 1cv8 Платные (руб)

Внешняя компонента в виде библиотеки (.dll файл), позволяющая посылать команды и получать ответы по протоколу WebSocket из 1С. Компонента работает только на стороне "клиента".

4440 руб.

22.06.2020    17884    17    33    

21

Разработка внешних компонент Программист Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Платные (руб)

Как известно, стремление сделать свою рекламную продукцию запоминающейся и выделяющейся — верный путь к успеху. Сегодня, мы поговорим с вами о том, что можно сделать с обычным черно-белым QR-кодом, чтобы он стал более живым и привлекательным. Если вам не терпится попробовать сгенерировать QR-код с логотипом компании, то эта обработка для вас!

2400 руб.

22.06.2016    31276    5    4    

9
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. AlX0id 16.02.16 08:55 Сейчас в теме

Спасибо, будет что почитать на досуге :)
2. Serginio 942 16.02.16 09:45 Сейчас в теме
Большое спасибо за спасибо.
3. avz_1C 10 16.02.16 12:32 Сейчас в теме
Спасибо. Написано очень толково.
Я систематизировал свои знания по данному предмету, при помощи Вашей статьи.
4. Serginio 942 16.02.16 12:52 Сейчас в теме
Спасибо. Старался. Рад, что мои труды не пропадают зря.
5. O-Planet 6441 17.02.16 03:28 Сейчас в теме
Спасибо за статью. У меня com+ на с++ (Builder). Не совсем понимаю, как внутри этого объекта обратиться к глобальному контексту 1С. Объекты я передаю через VARIANT, например:

STDMETHODIMP TServerImpl::Make(VARIANT Object, int Numb, BSTR FileName)
{
bool Res=mycells->Make(Numb,AnsiString(WideString(FileName).c_bstr()));
Variant(Object).OleFunction("Вставить","Ок",(Res?"yes":"no"));
return S_OK;
}

Но как получить доступ в этой функции к глобальному контексту 1С, чтобы вызвать, например, NewObject? Что передать на вход? Или можно как-то подключиться к самой 1С? Вопрос - как? Не через OLE же. И теоретически, этот com может быть использован и не 1С. Есть возможность проверить, кто его создал и использует?
6. Serginio 942 17.02.16 07:33 Сейчас в теме
Ну судя по
ТипГК = ГК1С.GetType();

App1C = ГК1С.AppDispatch;

 

result = ТипГК.InvokeMember(binder.Name, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod, null, App1C, new object[]{value}););
Показать


Адрес функции берется из VMT ГК1С, а в EAX засылается ГК1С.AppDispatch
7. Serginio 942 17.02.16 07:38 Сейчас в теме
8. Serginio 942 17.02.16 08:27 Сейчас в теме
Адреса Idispatch GetIDsOfName(), Invoke()
То есть ссылку на Idispatch берется из передаваемого объекта при Init, а объект подставляется AppDispatch
9. Serginio 942 17.02.16 08:33 Сейчас в теме
Помню в Delphi для реализации интерфейса создавалось поле внутри объекта, а в методах интерфейса были заглушки которые корректировали this по смещению поля и вызывали реальные методы интерфейса объекта
10. frkbvfnjh 802 27.02.16 08:31 Сейчас в теме
Лююююююди! Кто нибудь может накидать шаблон на Delphi, что бы можно было работать в глобальном контексте? C# вообще не понимаю, да и COM технология с трудом дается, но очень хочется пользоваться функционалом платформы, поэтому хотелось бы шаблон native-компоненты на Delphi. Я так понимаю для людей, оставивших здесь комментарии, это не составит никакого труда. Сейчас для написания внешних компонент пользуюсь шаблоном из публикации http://infostart.ru/public/168254/. Сжальтесь над немощным... ну что Вам стоит?
11. Serginio 942 27.02.16 09:03 Сейчас в теме
(10) Тебе лучше обратиться сюда http://infostart.ru/public/88060/
Только вот глобальный Контекст это COM.
12. NittenRenegade 110 20.06.18 11:08 Сейчас в теме
Я внедряю CefSharp во внешнюю компоненту. Сложность в том, что её не скомпилируешь в одну dll. У него множество файлов-зависимостей разных типов, без которых например подпроцесс для отображения содержимого страницы просто не запустится.
Когда эти файлы лежат рядом с запускаемым приложением, у меня всё работает. Но когда я компилирую библиотеку и подключаю её из 1С, у меня пустой экран как если бы подпроцесс не стартовал. Подозреваю, дело в зависимостях. Куда сложить файлы зависимостей чтобы они подтянулись к моей dll? Или может как-то иначе эти зависимости прописать в самой dll
15. Serginio 942 20.06.18 12:03 Сейчас в теме
На самом деле если все dll в одной папке и есть доступ к папке для текущего пользователя, то все должно быть нормально
Оставьте свое сообщение