gifts2017

Использование внешних COM-компонент (.dll) или любых клиентских методов в регламентных заданиях серверной базы.

Опубликовал Евгения Карук (ekaruk) в раздел Программирование - Практика программирования

Для расширения возможностей платформы 1С существует огромное количество внешних компонент (дополнительные функции, взаимодействие с софтом и железом других производителей, ключи защиты).
К сожалению, большинство из них написано на технологии .COM и не могут использоваться на сервере.
Для использования в регламентных заданиях серверной базы их приходится переписывать на Native API.
Однако, иногда нет возможности переписать компоненту на новую технологию, но нужно вызвать ее в регламентном задании на сервере.

Например, не получится переписать компоненту, если вы не её автор и исходников просто нет. Либо если для ее работы недостаточно поддерживаемых технологией Native API простейших типов (число, строка, булево, дата).

При работе с файловой базой особых проблем нет.  Регламентное задание вызывается в фоновом процессе обычного пользователя. Поэтому ему доступны клиенские вызовы. В серверной базе при запуске регламентного задания клиентского контекста нет, соответственно вызов ПодключитьВнешнююКомпоненту() недоступен.

Подробнее о том, почему недоступен, можно почитать на ИТС.

В этом случае можно вызывать компоненту на клиенте. Для этого достаточно выполнить из регламентного задания на сервере запуск еще одного сеанса 1С в котором на клиенте выполнить нужные действия. Ну и не забыть потом завершить запущенный сеанс.

Допустим, у нас в регламентном задании выполняется формирование и сохранение отчета, использующего для склонения ФИО внешнюю COM-компоненту NameDeclension.dll. На файловой базе такое регламентное задание будет работать корректно, на серверной компоненту подключить не получится.

Для устранения проблемы добавим в модуль регламентных заданий процедуру, которая в серверном режиме запустит еще один сеанс и в нем выполнит из внешней обработки вызов формирования отчета на клиенте.

#Если Клиент Тогда

Процедура ВыполнитьФормированиеИСохранениеОтчета() Экспорт

    Если ПодключитьВнешнююКомпоненту("ОбщийМакет.NAMEDECL","Скл",ТипВнешнейКомпоненты.COM) Тогда
	 Компонента = Новый ("AddIn.Скл.NameDeclension");
         //Тут код формирования и сохранения отчета 
    Иначе	
	 ЗаписьЖурналаРегистрации("РеглЗадания", УровеньЖурналаРегистрации.Ошибка,,, 
                                   "Не удалось подключить внешнюю компоненту на клиенте");
    КонецЕсли; 

КонецПроцедуры
	
#Иначе
	
Процедура ВыполнитьФормированиеИСохранениеОтчета() Экспорт
	
	ВыполнитьОперациюНаКлиенте("РеглЗадания.ВыполнитьФормированиеИСохранениеОтчета()"); 

КонецПроцедуры
		
Процедура ВыполнитьОперациюНаКлиенте(ПараметрДляВыполнения) Экспорт

	ИмяПользователя = "";
	ПарольПользователя = "";
	ПутьКВнешнейОбработке = "c:/temp/Автозапуск.epf";
	
	Кавычка = """";

	КаталогBIN = КаталогПрограммы();
	
	ПутьККонфигурации = СтрокаСоединенияИнформационнойБазы();
	ПутьККонфигурации = СтрЗаменить(ПутьККонфигурации, Кавычка, Кавычка + Кавычка);
	
	СтрокаЗапуска = Кавычка + КаталогBIN + "1cv8.exe" + Кавычка + " ENTERPRISE"
		+ " /IBConnectionString " + Кавычка + ПутьККонфигурации + Кавычка
		+ " /N "                  + Кавычка + ИмяПользователя + Кавычка
		+ " /P "                  + Кавычка + ПарольПользователя + Кавычка
		+ " /Execute  "           + Кавычка + ПутьКВнешнейОбработке + Кавычка
		+ " /C  "                 + Кавычка + ПараметрДляВыполнения + Кавычка;

	ЗапуститьПриложение(СтрокаЗапуска);	

КонецПроцедуры
 
#КонецЕсли

Код внешней обработки, которая просто вызовет в контексте клиента печать нужного отчета из модуля регламентных заданий и завершит сеанс после формирования отчета.

Попытка
    Выполнить(ПараметрЗапуска);
Исключение
КонецПопытки;
ЗавершитьРаботуСистемы(Ложь);

Удобство решения в том, что при настройке регламентных заданий не важно, в каком режиме будет выполняться запуск задания. Если база файловая, то сразу запустится нужная процедура. Если база серверная и при запуске клиентский контекст отсутствует, то выполнится инициализация нового сеанса и в нем процедура корректно отработает в контексте клиента.

Код для обычного приложения. Теоретически полностью аналогично будет работать и в управляемом.

p.s. Также этот подход можно использовать для выполнения любых клиентских процедур в регламентных заданиях.

 


См. также

Подписаться Добавить вознаграждение

Комментарии

1. Алексей 1 (AlX0id) 11.12.14 00:13
Гм.. А что насчет лицензий? Какой-то не очень дешевый способ обхода, если на каждого юзера по доп.лицензии надобно.. Да и старт-стоп клиента на сервере - тоже не самый безнакладный процесс..Эт прям вот оооочень сильно надо захотеть именно эту компоненту запустить..
2. Евгения Карук (ekaruk) 11.12.14 00:23
(1) AlX0id, В данном случае речь в основном о кратковременном регламентном запуске процедур. Например, выгрузка отчетов, синхронизация с АТС, выгрузка/загрузка данных на сайт, считка информации со стороннего железа/сервисов. С точки зрения лицензий проблем не вижу. Лицензия занимается исключительно на время выполнения операции - в большинстве случаев несколько минут. Запуск и завершение сеанса тоже никакой особой загрузки не создает.
Конечно, это не идеальное решение. Скорее костыль, но вполне универсальный и стабильно работающий.
3. Валерий Максимов (theshadowco) 11.12.14 07:22
По опыту скажу, все ситуации, когда надо было использовать клиентский функционал на сервере можно переработать / переосмыслить таким образом, что это не требуется.
Использование запуска клиентских сессий на сервере еще чревато тем, что есть вероятность получения модального окна и зависшей сессии.
alexscamp; baton_pk; KAPACEB.AA; tehas; IfYouWant_YouCan; +5 Ответить 1
4. Евгения Карук (ekaruk) 11.12.14 08:48
(3) theshadowco, Как ни переосмысливай, .COM - компоненты банально не работают на сервере. Альтернатив иногда нет. Проблемы с зависшими сеансами возможны. Но вообще от кода зависит. Если написан корректно, то никаких модальных окон там нет. У нас были периодически такие зависания, но именно из проблем с внешними системами. Решали выполнением при старте обработки автозавершения через обращение к кластеру всех сеансов текущего пользователя старше одного часа. Разумеется, пользователь отдельный именно для регламентных заданий.
vslimv; Selderey; KAPACEB.AA; help1Ckr; artbear; +5 Ответить 2
5. Олег Филиппов (comol) 11.12.14 09:44
А сделать DCOM ну или на край .NET обёртку не?
6. Евгения Карук (ekaruk) 11.12.14 10:13
(5) comol, В смысле обёртку, которая будет обращаться к .dll а сама подключаться к 1С как Native API ? Или что-то другое имелось в виду?
Теоретически тоже возможно. Из минусов, появляется дополнительная прослойка и необходимость сериализации/десериализации данных, если для них простых типов Native API недостаточно.
Но лично я не умею такие обёртки писать, необходимости пока не было.
7. Asmody (Asmody) 11.12.14 10:15
Самый большой минус технологии СOM — одноплатформенность. Как только у вас появляется сервер на Linux, о технологии COM приходится забыть.
8. Юрий Гончарук (yukon) 11.12.14 13:13
(4) ekaruk,
.COM - компоненты банально не работают на сервере

Вот те на. Всю жизнь обмен через COM-соединение отлично работал на сервере, а тут оказывается что он "банально не работает". Это как?

UPD.
В серверной базе при запуске регламентного задания клиентского контекста нет, соответственно вызов ПодключитьВнешнююКомпоненту() недоступен.

ПодключитьВнешнююКомпоненту (AttachAddIn)
Доступность: 
Тонкий клиент, веб-клиент, сервер, толстый клиент, внешнее соединение. 

Может я действительно чего-то не понимаю, но в чем собственно проблема?
9. Евгения Карук (ekaruk) 11.12.14 14:29
(8) yukon, Добро пожаловать в клиент-серверную архитектуру :)
Не подключаются на сервере com-компоненты. Уже очень давно.
Работают в файловой базе, так как доступен толстый клиент. Но не в серверной.

http://its.1c.ru/db/v83doc#bookmark:dev:TI000001197

32.3. Особенности работы на сервере
При работе на сервере «1С:Предприятия» допустимо использовать только компоненты, разработанные по технологии Native API, которые могут быть как отдельными файлами, так и упакованными в специальные ZIP-архивы.

В СП описано 2 варианта подключения. Первый только для Native API. Второй для любых.
Но:
Описание варианта метода:
Компонент должен быть выполнен по технологии COM и зарегистрирован в реестре MS Windows.
Эти компоненты совместимы с компонентами 1С:Предприятия 7.7.
Внимание! Вариант метода не работает на сервере и во внешнем соединении.

В документации на ИТС по ссылке выше подробнее.
10. Евгения Карук (ekaruk) 11.12.14 14:51
(8) yukon, Обмен через COM- соединение Вы имеете в виду подключение через comcntr.dll?
Оно работает корректно.
Это не внешняя компонента для 1С, это компонента для Виндовс.
Она не просто загружается в 1С, а устанавливается в Виндовс через службы компонентов.
Не могу объяснить, в чем разница, но технология другая.

Возможно, кто-то другой по принципу ее работы подскажет.
11. Юрий Гончарук (yukon) 11.12.14 18:18
(10) ekaruk,
Все понятно. Действительно, компоненты в "старом" формате на сервере недоступны. В общем-то они могут регистрироваться через regsvr32 (увы, необязательно), а далее через Новый COMОбъект.

А вот с теми кто не может регистрироваться придется держать отдельного клиента, который через обработку ожидания будет выполнять действия. Ваш вариант решает, конечно, задачу, но уж сильно "костыльно".
12. Евгения Карук (ekaruk) 11.12.14 18:23
(11) yukon, Насколько я понимаю, внешние компоненты не могут использоваться на сервере независимо от того, зарегистрированы ли они через regsvr32. Т.е. это принципиальное ограничение. Они просто не подключаются в 1С.
Возможно, чего-то не учитываю и есть нюансы.
По comcntr.dll мне самой хотелось бы понять, как она работает. Но информации не нашла.
13. Александр Макаров (DarLord) 17.12.14 09:48
(4) ekaruk, в 1С зависшие сессии вообще беда, у нас при одновременной работе более 150 человек постоянно появляются зависшие сеансы и блокировки базы, бороться с этим очень сложно...
14. kiruha Дронов (kiruha) 17.12.14 10:09
Я так понимаю автор имел ввиду - что не работают некоторые com.
Может автор 32 битную запускает ? Или с визуализацией ?
Вообще что это было ?

У нас используется много разных com на сервере - и все прекрасно работает и при очень большой нагрузке
theshadowco; +1 Ответить 1
15. Евгения Карук (ekaruk) 17.12.14 10:35
(14) kiruha, Мы говорим о внешних компонентах, выполненных по технологии .COM
Которые подключаются с использованием синтаксиса ПодключитьВнешнююКомпоненту().
О том, почему они не работают, описано выше в комментариях и по ссылкам на ИТС.
16. lefthander (lefthander) 17.12.14 10:49
Спасибо за идею. Попробую решить одну задачку. Смысл ее в том что бы по заданию подключиться по COM к бухгалтериям и получить данные в отчет, и отчет разослать по списку. В клиенте все нормально, а вот в регламентном задании - швах.
17. Олег (oleg_km) 17.12.14 11:14
Мне кажется, нет смысла делать ВК в технологии COM. Лучше тогда делать и использовать просто COM.
BorovikSV; gislink; +2 Ответить
18. Adapter Бахтыреев (adapter) 17.12.14 11:57
Интересный пример, но немного не удачный. ВыполнитьПечатьОтчета - из принтера на сервере выведет? Мне бы отчет на моем принтере нужен, а на сервере вообще принтер не подключен. Это только в обычном приложении контекст клиента и сервера выполняется на юзерском компе, для совместимости с управляемым.

И во многих случаях проблемы использования com-компонент вызваны особенностями разрядности Windows (х32, х64) а не контекстом выполнения.
theshadowco; +1 Ответить 1
19. Евгения Карук (ekaruk) 17.12.14 12:46
(18) adapter, Тут речь о регламентных операциях, которые используют именно инфраструктуру сервера. Немного поменяла название процедуры в коде, чтобы было понятнее.
Разрядности Windows (х32, х64) это отдельная история. Но по ней уже вроде достаточно информации. Как именно оборачивать компоненту, чтобы она работала на Виндовс с другой разрядностью. Эту тему уже много раз поднимали.
20. Максим *** (premier) 19.12.14 15:19
(10) Возможно, кто-то другой по принципу ее работы подскажет.
А всё достаточно просто:
COM объект - самостоятельная программа, предоставляющая для работы с ней свои интерфейсы, через которые программы, поддерживающие технологию COM (теперь уже принято её ActiveX называть) могут обращаться к его свойствам и методам..
А вот внешняя COM компонента - это вспомогательная программа (плагин для 1С), которая взаимодействует с 1С, через только через интерфейсы, предоставляемые самой системой 1С:Предприятие. Ну и, соответственно наша внешняя COM компонента - плагин может быть запущена только в рабочем процессе 1С Предприятия.
21. kiruha Дронов (kiruha) 19.12.14 17:36
А вариант с подключением через com к 1С - там (внешнее соединение) компоненты тоже не работают ?
22. Игорь Матюшин (Nebiros777) 24.12.14 11:46
Чтобы не запускать еще один сеанс в конфу добавляется "внутренняя" обработка с макетом, в котором двоичные данные из DLL. Потом все нормально подключается на сервере без проблем: Из внешней обработки подключение DLL невозможно, обязательно нужно вшивать в конфу, если хотите пользоваться "Native" компонентой.
23. Евгения Карук (ekaruk) 24.12.14 13:04
(22) Nebiros777, С Native компонентами проблем никаких нет. Они отлично подключаются на сервере и без встраивания макетов.
Проблема только с .COM компонентами
(21) kiruha, с .com подключение К 1С проблем нет. Выше уже обсудили почему.
24. kiruha Дронов (kiruha) 24.12.14 15:35
А почему тогда нельзя просто
Коннектор= Новый COMObject("V82.COMConnector");
База= Коннектор.Connect(СтрокаПодключения);
База.МойМодуль.МояПроцедураСВнешнейКомпонентойВнутри();
25. Евгения Карук (ekaruk) 24.12.14 15:49
(24) kiruha, Потому что МояПроцедураСВнешнейКомпонентойВнутри() не сможет использовать внешнюю компоненту на сервере.
Абсолютно пофиг, вызывается она снаружи или изнутри.
26. kiruha Дронов (kiruha) 24.12.14 15:52
Она вызывает ее во внешнем соединении а не на сервере.
Есть dll которую можно скачать и проверить ?
27. Евгения Карук (ekaruk) 24.12.14 16:00
(26) kiruha, Та копонента, что у меня в примере.
http://manual1c.ru/sklonenie-familii-imeni-i-otchestva-po-padezham-v-1s-8-2/
Где-то уже есть ее Native аналог, но эта вроде как раз .COM
Попробуйте подключить в регламентном задании на сервере (не в толстом клиенте)
28. kiruha Дронов (kiruha) 29.12.14 20:12
Com сессия прекрасно вызвалась из под сервера, в отладчике показывается как внешнее соединение, но подключить внешнюю компоненту в этой сессии не удалось.
По какой причине не понял
Так что ваш метод пока единственный )
29. Евгения Карук (ekaruk) 29.12.14 22:42
(28) kiruha, В режиме внешнего соединения нет клиентского контекста. Соответственно и .com компоненты не подключаются.
30. bulpi bulpi (bulpi) 14.01.15 16:42
Народ, что же вы все уперлись в вырывание гланд через задний проход??? Ну если все равно придется запустить клиентский сеанс, тогда зачем его запускать через жопу сервер? Запустите вместо регламентного задания клиентский сеанс, используя внешний планировщик (да хоть встроенный Windows)
jan27; theshadowco; Dach; +3 Ответить
31. Alexei Zhovner (jan27) 09.12.15 16:01
(0) лучше использовать
ПрекратитьРаботуСистемы()
32. zaverax (zaverax) 15.01.16 10:06
Подскажите плиз...раньше свои внешние компоненты (COM) использовал в 1c8.2
там строка была Компонента = Новый ("AddIn.SW");
сейчас в 1с8.3 (управляемая форма) надо писать как тут описано в примере
Компонента = Новый ("AddIn.Скл.NameDeclension");
Вот интересует NameDeclension - что это такое? откуда брать?
33. Сергей Смирнов (Serginio) 15.01.16 10:33
А зачем ВК на сервере? Смысл ВК в событиях, окнах и доступе к глобальному контекста 1С.
Используй COM. А например используя Библиотеки Net ты можешь написать, что угодно http://infostart.ru/public/238584/

Вот библиотека склонения http://yeaahcode.blogspot.ru/2015/01/lingvonet.html
34. Сергей Смирнов (Serginio) 15.01.16 10:45
На самом деле интерес представляет Com объект который внутри будет вызывать методы IlanguageExtender
На подобии http://infostart.ru/public/345658/ только в обратную сторону.
А твой подход я применял еще в 8.1 для сохранения в эксель итд
35. Евгения Карук (ekaruk) 15.01.16 11:05
(32) zaverax, Это стандартная компонента для склонения.
"NameDeclension" это прописанное в ней имя.
Вообще если пишите сами, то лучше переделать сразу правильно на Native.
Будет стабильнее работать и удобнее.
Указанный в статье подход можно использовать исключительно если есть старая уже готовая компонента и нет возможности ее изменить (т.е. компонента чужая и банально нет исходников или специалистов по ней).
36. zaverax (zaverax) 15.01.16 16:29
(35) ekaruk,
а есть пример написания COM и Native в Delphi?

у меня в делфи вот так описано CreateAddIn('sw', ObjectGUID, TDM1,'AddInFPList');

в 1с8 вызывал Компонента = Новый ("AddIn.SW");

если теперь вызываю Компонента = Новый ("AddIn.SW.TDM1"); - то ошибка Тип не определен...
37. Сергей Смирнов (Serginio) 15.01.16 17:27
ПодключитьВнешнююКомпоненту(<Местоположение>, <Имя>, <Тип>)

Вот Имя и будет вторым после Addin
38. Сергей Смирнов (Serginio) 15.01.16 17:52
(0) Проблема еще в том, сами ВК 32 разрядные.
Кстати в http://infostart.ru/public/238584/ есть пример обмена данными по TCP/IP
Смысл в том, что экономишь на запуске 1С, компоненты итд.
А так созданшь обработку, в которой запускаешь Tcp/IP клиента и обмениваешься данными.


Аналогичный обмен здесь
http://infostart.ru/public/434771/
39. zaverax (zaverax) 15.01.16 18:24
(37) Serginio,
меня интересует что должно быть написано третим...AddIn.SW.хххххх - вместо ххххххх
что за класс?

CreateAddIn('sw', ObjectGUID, TDM1,'AddInFPList')....TDM1 - это класс который создается...но если я его подставляю в 1С то ошибка Тип не определен...
40. Евгения Карук (ekaruk) 15.01.16 18:28
(36) zaverax, Тут не подскажу, к сожалению.
С нюансами разработки и регистрации внешних компонент я знакома плохо.
41. Сергей Смирнов (Serginio) 15.01.16 19:39
42. kiruha Дронов (kiruha) 01.03.16 17:08
Никто не заметил комментария (31) ПрекратитьРаботуСистемы
Описание:

Завершает работу системы не зависимо от наличия модальных диалогов, открытых редактируемых форм документов и справочников и т.д. При этом не вызываются процедуры-обработчики событий завершения работы системы.
43. Евгения Карук (ekaruk) 01.03.16 17:13
(42) kiruha, (31) jan27,
Да, пожалуй, ПрекратитьРаботуСистемы() надежнее.
У меня ЗавершитьРаботуСистемы() тоже вполне хватало.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа