|
Как-то можно инициировать выполнение кода 1с внешней компонентой? | ☑ | ||
---|---|---|---|---|
0
rphosts
22.05.18
✎
05:15
|
Есть dll (в смысле как надо так и будет переписано если в этом вопрос), как-то можно заставить из длл на клиентском компе инициировать выполнение кода 1С (ИБ 1С уже запущена на клиенте)?
|
|||
1
craxx
22.05.18
✎
05:29
|
(0) Зашить в ресурс dll внешнюю обработку и выполнять код из нее. Так кажись ключ защиты раруса работает, насколько я помню
|
|||
2
rphosts
22.05.18
✎
05:32
|
(1) не-не-не, нужно заставить выполняться код клиентского кода формы. С торговым оборудованием ведь это как-то сделано.
|
|||
3
Emery
22.05.18
✎
07:01
|
Т.е. задача состоит в том, чтобы из внешней компоненты (ВК) обратиться к 1С как к серверу, ну и, соответственно, выполнить некоторый код в «семерке» либо «восьмерке»?
Если так, то из ВК надо инициировать внешнее событие, которое подхватывает обработчик «ОбработкаВнешнегоСобытия(Источник, Сообщение, Данные)» В ВК нужно воспользоваться интерфейсом 1С IAsyncEvent и написать что-то, вроде: if(pIAsyncEvent) { pIAsyncEvent->SetEventBufferDepth(2); // Определяет количество одновременных событий pIAsyncEvent->ExternalEvent(L"Emery", L"Hello from DllMain()", L"Привет, Emery!"); //Sleep(1000); pIAsyncEvent->ExternalEvent(L"Emery2", L"Hello from DllMain()", L"Как твои дела?"); //AfxMessageBox("pIAsyncEvent <> NULL!"); } else { AfxMessageBox("pIStatusLine == NULL!"); } А в 1С, в предопределенной процедуре, написать примерно следующее: Процедура ОбработкаВнешнегоСобытия(Источник, Сообщение, Данные) Если Источник = "Emery" Тогда Сообщить(Сообщение + " : " + Данные); Иначе Сообщить(Источник + " : " + Сообщение + " : " + Данные); КонецЕсли КонецПроцедуры // ОбработкаВнешнегоСобытия() Второй способ это создать в ВК экземпляр OLE-сервера 1C и тогда мы сможем вызывать оттуда глобальные процедуры 1С. Здесь плохо то, что создается новый экземпляр 1С. Теоретически можно подключиться к уже существующему экземпляру 1С, как OLE-серверу, но никто не знает как. Другие варианты это уже специфика 1С77. Например, очень хороший вариант подключиться к «семерке», как к DDE-серверу и выполнить нужную глобальную процедуру. Кстати на этом принципе у меня работает нынешняя версия «зарплаты», только вызов идет не из ВК, а из внешнего приложения Visual FoxPro (которое вызывается из 1С), но в данном случае, это не принципиально. Опять же, те в «семерке» есть штатный обработчик «ОбработкаОжидания(<ИмяПроцедуры>, <ИнтервалВызова>)». Можно периодически, например, каждую секунду делать опрос некоего состояния (например, наличие существования временного файла, который создает ВК) и, если оно выполнено, то вызывать соответствующую процедуру 1С. Вот, пожалуй, и все, что я знаю. |
|||
4
rphosts
22.05.18
✎
07:03
|
(3) Спасибо! Буду попробовать.
|
|||
5
Сияющий в темноте
22.05.18
✎
09:54
|
Сказано,что внешняя компонента получает Dispatch к 1с через Init,у него можно получить какие то интерфейсы к 1с,а также основной интерфейс,если у вас восьмерка,только во имя метода не помню.
|
|||
6
Emery
22.05.18
✎
11:14
|
(5) > внешняя компонента получает Dispatch к 1с через Init
Функция Init(IDispatch *pConnection) дает доступ к указателю pConnection, который можно сохранить глобально, типа: m_pIDispatch = pConnection; и воспользоваться затем в другом месте для получения заданных интерфейсов 1С, скажем IAsyncEvent: IAsyncEvent *pIAsyncEvent = NULL; m_pIDispatch->QueryInterface(IID_IAsyncEvent, (void **) &pIAsyncEvent); Но таким образом мы не можем получить «основной интерфейс». Вот, что на эту тему пишут в Интернете (не помню уже, откуда скачал) относительно 1С77: // У нас есть два указателя IDispatch: // 1. Передаваемый системой в качестве параметра метода Init. Через него можно получать интерфейсы // 1С:Предприятия, но нельзя вызывать его методы, например: IExtWndsSupport *pIExtWndsSupport = NULL; m_IDispatch->QueryInterface(IID_IExtWndsSupport, (void **) &pIExtWndsSupport); //[helpstring("method GetAppMainFrame")] HRESULT GetAppMainFrame([in,out]HWND *hwnd); //[helpstring("method GetAppMDIFrame")] HRESULT GetAppMDIFrame([in,out]HWND *hwnd); //[helpstring("method CreateAddInWindow")] HRESULT CreateAddInWindow([in]BSTR bstrProgID, [in]BSTR bstrWindowName, [in]long dwStyles, [in]long dwExStyles, [in]RECT *rctl, [in]long Flags, [in,out]HWND *pHwnd, [in,out]IDispatch **pDisp); // 2. Находящийся в свойстве AppDispach. Он может использоваться для вызова методов 1С:Предприятия, // при этом используется механизм OLE Automation. // Получение того указателя IDispatch, который позволяет вызывать методы 1С. Но здесь тоже два варианта, // Первый вариант это использование вновь созданного экземпляра «семерки», здесь довольно большой код, вот его начало: //V1CEnterprise.Application - версия независимый ключ; //V77.Application - версия зависимый ключ; //V77S.Application - версия зависимый ключ, SQL-версия; //V77L.Application - версия зависимый ключ, локальная-версия; //V77M.Application - версия зависимый ключ, сетевая-версия. CLSID clsid = {0}; HRESULT hr = CLSIDFromProgID(L"'V1CEnterprise.Application ", &clsid); if(FAILED(hr)) { AfxMessageBox("Не найден clsid для 'V1CEnterprise.Application'!"); CoUninitialize(); return S_FALSE; } // Основной интерфейс, за который мы будем "дёргать" IDispatch *pv77; // Создаём инстанцию 1С Предприятия. // CLSCTX_LOCAL_SERVER – это значит, что 1С Предприятие // будет запущено в виде отдельного процесса – по-другому оно не умеет. IDispatch *pIDispatch = NULL; IClassFactory *pCF = NULL; IUnknown *pIUnknown = NULL; hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC, IID_IDispatch, (void **) &pIDispatch); // Только для CLSCTX_LOCAL_SERVER //IID_IClassFactory, (void **) &pCF); // Только для CLSCTX_LOCAL_SERVER И т.д. // Второй вариант, это пока никому неизвестный, когда есть интерфейс при флаге CLSCTX_INPROC или // CLSCTX_INPROC_SERVER. Пока нам доступен только такой вызов: hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC, IID_IUnknown, (void **) &pIUnknown); // Это работает для INPROC сервер, но ничего нам реально не дает! Но можно ли здесь из pIUnknown получить pIDispatch – большой вопрос, так как обычные манипуляции не срабатывают. |
|||
7
H A D G E H O G s
22.05.18
✎
11:20
|
Жесть какая
|
|||
8
H A D G E H O G s
22.05.18
✎
11:24
|
В процедуре Init() параметр PConnect сохраняем в переменной
PConnect:IDispatch; В процедуре CallAsFunc() (не раньше) получаем контекст 1С и храним в AppDispatch:OleVariant; AppDispatch:=OleVariant(PConnect).AppDispatch; |
|||
9
Рэйв
22.05.18
✎
11:24
|
Вставь в модуль внешнего соединения:
//--- Функция ИсполнитьВн(КодВыполнить, ВспомПараметр= "") Экспорт Ответ= "ОК";//Если ничего не нужно будет возвращать, то при отсутствии ошибок в коде вернется просто ОК //Т.к. переданный код может быть с ошибками, то завернем его исполнение в попытку. Попытка Выполнить(КодВыполнить); Исключение //если все таки ошибка, то вернем ее текст Ответ="ОШИБКА:"+ОписаниеОшибки(); КонецПопытки; Возврат Ответ; КонецФункции //---- и выполняй любой код по COM соединению с возвратом любого результата |
|||
10
H A D G E H O G s
22.05.18
✎
11:25
|
Ну и потом как душе угодно
ЗапросДанных := LocalDispatch.NewObject('Запрос'); ЗапросДанных.Текст := ' ВЫБРАТЬ ПЕРВЫЕ 1' + ' АСФСоответствияТМИОрганизацийиИхОбособленныхПодразделений.Организация,' + ' АСФСоответствияТМИОрганизацийиИхОбособленныхПодразделений.АСФОбособленноеПодразделениеОрганизации' + ' ИЗ' + ' РегистрСведений.АСФСоответствияТМИОрганизацийиИхОбособленныхПодразделений КАК АСФСоответствияТМИОрганизацийиИхОбособленныхПодразделений' + ' ГДЕ' + ' АСФСоответствияТМИОрганизацийиИхОбособленныхПодразделений.ТранспортныйМодульЕГАИС = &ТранспортныйМодульЕГАИС'; ЗапросДанных.УстановитьПараметр('ТранспортныйМодульЕГАИС', ТранспортныйМодуль); Выборка := ЗапросДанных.Выполнить().Выбрать(); if Выборка.Следующий() = true then begin Организация := Выборка.Организация; АСФОбособленноеПодразделениеОрганизации := Выборка.АСФОбособленноеПодразделениеОрганизации; end |
|||
11
H A D G E H O G s
22.05.18
✎
11:25
|
ЗапросДанных := LocalDispatch.NewObject('Запрос');
заменить на ЗапросДанных := AppDispatch.NewObject('Запрос'); |
|||
12
H A D G E H O G s
22.05.18
✎
11:26
|
Com-соединение не нужон.
|
|||
13
H A D G E H O G s
22.05.18
✎
11:27
|
А всякие извращения с созданием своего инстанса - это уже ближе к теме написания ВК без обращений к реестру Windows, я недавно выкладывал статью, но меня отговорили, опасносте.
|
|||
14
H A D G E H O G s
22.05.18
✎
11:27
|
Ну или создание инстанса - к извращениям в C++/ C# . В этих ЯП надо пострадать.
|
|||
15
H A D G E H O G s
22.05.18
✎
11:30
|
Не забываем, что AppDispatch нестабильно работает с глобальным контексом на серверной стороне клиент-сервера. Например, он не увидит ЗаполнитьЗначениеСвойств(). Для обхода - пилим глобальный ОМ, в котором будет реализация
Процедура ЗаполнитьЗначенияСвойствПереопределенный(Приемник, Источник,СписокСвойств=Неопределено,ИсключаяСвойства=Неопределено) Экспорт ЗаполнитьЗначенияСвойств(Приемник,Источник,СписокСвойств,ИсключаяСвойства); КонецПроцедуры И вызываем AppDispatch.ЗаполнитьЗначенияСвойствПереопределенный() |
|||
16
H A D G E H O G s
22.05.18
✎
11:31
|
Не забываем, что ВК криво работает с несколькими пользователями на сервере. Тут уже появляется необходимость блокировок общих ресурсов и выставление флага IsMultiThread:=true;
в секции иницииации dll |
|||
17
H A D G E H O G s
22.05.18
✎
11:33
|
Не забываем, что в ВК нет препроцессора. Поможет это в глобальном ОМ
Функция ЭтоСервер() Экспорт Результат=Ложь; #Если Сервер Тогда Результат=Истина; #КонецЕсли Возврат Результат; КонецФункции |
|||
18
Tateossian
22.05.18
✎
11:35
|
Я из Java ходил так в 1С - в JVM тоже свой inproc server. В итоге подцеплял api в одной dll. Было весело:)
|
|||
19
Вафель
22.05.18
✎
11:36
|
(17) а через попытку нельзя вычислить?
|
|||
20
Tateossian
22.05.18
✎
11:40
|
(16) Можно подключать с разными именами и даже с генератором dll'ек - тогда будет псевдопараллельность.
Помню была компонента, то ли для печати, то ли для операций с текстом. Если печатать этикетки фоновыми заданиями с одной dll - часто были косяки. А вот если наплодить dlleleк и c рандомным именем подключать - таки работать параллельно можно без всяких допилов мьютексов, семафоров и прочих радостей многопоточной парадигмы:) |
|||
21
H A D G E H O G s
22.05.18
✎
12:19
|
(20) Не по фуншую.
|
|||
22
rphosts
23.05.18
✎
06:02
|
О!
Ещё раз спасибо! |
|||
23
Сияющий в темноте
23.05.18
✎
11:15
|
И,самое главное,компонента-исполнитель,то есть в нее управление передается при вызове какого то метода,ну или,когда мы зарегестрировали обратный вызов из системных функций.
Чтобы компонента была генератором событий,в ней нужно создавать отдельный поток,но его вызовы в 1с будут идти через удаленный вызов процедур,т.к.у него другое размещение(apartment) в итоге,из потока проще в web или http сервис в 1с обращаться,будет быстрее,а вместо потока запускать отдельный процесс,следующий вопрос будет-а нужна ли нам внешняя компонента? |
|||
24
Сияющий в темноте
23.05.18
✎
11:16
|
компонента в версии 2.0 должна допускать содание нескольких экземпляров обьекта,так что там разные имена не нужны.
|
|||
25
H A D G E H O G s
23.05.18
✎
11:19
|
(23) (24) Вы пишите какую - то странь.
|
|||
26
H A D G E H O G s
23.05.18
✎
11:20
|
(24) "компонента в версии 2.0 должна допускать содание нескольких экземпляров обьекта,так что там разные имена не нужны."
Адресное пространство будет едино. DLL-ка в памяти то одна. |
|||
27
H A D G E H O G s
23.05.18
✎
11:31
|
(23) Никакого RPC из отдельного потока вызываться не будет, несмотря на Apartment, так как ВК - это внутрипроцессный сервер.
|
|||
28
H A D G E H O G s
23.05.18
✎
11:31
|
Web сервисы имеют смысл только на стороне Сервера 1С.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |