Native внешняя компонента для оповещения по UDP или TCP

01.03.20

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

Native внешняя компонента для оповещения по UDP или TCP, которая реализует возможность в 1С передавать сообщения с сервера на клиента. Исходный код компоненты также представлен.

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
Внешняя компонента MyLib
.zip 804,28Kb
25
25 Скачать (1 SM) Купить за 1 850 руб.
Внешняя компонента MyLib с исходным кодом
.zip 26,15Mb
29
29 Скачать (3 SM) Купить за 2 450 руб.

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

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

   Затем была изучена и протестирована типовая система взаимодействия. Эта система вполне подходила, но был жирный минус: она почему-то отказывалась работать на обычных формах. Так как работа шла в конфигурации УТ 10.3, то эта система также была отброшена. 

   Начался мучительный поиск внешней компоненты для передачи оповещений по UDP или TCP. Большинство найденных компонент работали только на платформе 1С win32, а у нас стояла платформа 64 бит. Подходящая компонента все же была найдена и протестирована. Но так как она не поддерживала передачу кириллицы, то также была отброшена. 

   В итоге решил написать свою компоненту, которую назвал MyLib, так как появилась идея использовать ее не только для udp или tcp оповещения, но по мере необходимости добавлять туда и другой функционал. Компонента написана при помощи Visual Studio 2013 на C++ по технологии Native. За основу был взят пример с диска ИТС, поэтому некоторые методы компоненты остались по наследству. Все свойства и методы можно писать как по русски, так и по английски.

   Свойства:

  1. PortTypeIsTCP (ПотоковыйТипПорта) - логический тип. Задает тип оповещения: по tcp или udp.
  2. LocalPort (Локальный порт) - целочисленный тип. Задает номер порта, который будет открыт для прослушивания.
  3. Status (Статус) - строковый тип. Служебное свойство, которое можно использовать для отладки.
  4. LogFile (ЛогФайл) - строковый тип. Здесь задается полный путь к текстовому файлу, в который компонента может писать логи. Это использовалось на этапе отладки, сейчас не применяется.

   Методы:

  1. ShowInStatusLine(<Текст>) (ПоказатьВСтрокеСтатуса) - этот метод достался по наследству. На 5 секунд выводит в строку статуса полученный Текст.
  2. ExternalEvent(<Источник>, <Событие>, <Данные>) (ВнешнееСобытие) - достался по наследству. Возвращает true - событие помещено в очередь, или false - очередь переполнена, обработка событий недоступна или неизвестная ошибка. Помещает событие в очередь, записывая источник события (Источник - тип Строка), наименование (Событие - тип Строка) и параметры события (Данные - тип Строка). При обработке события эти данные передаются процедуре ВнешнееСобытие(<Источник>, <Событие>, <Данные>). ExternalEvent доступен только на клиенте.
  3. LoadPicture(<ИмяФайла>) (ЗагрузитьКартинку) - достался по наследству. Загружает изображение из указанного файла и передает его в "1С:Предприятие".
  4. ShowMessageBox() (ПоказатьСообщение) - достался по наследству. Выводит сообщение о версии платформы.
  5. OpenPort() (ОткрытьПорт) - запускает прослушивание порта, который задан в свойстве LocalPort.
  6. ClosePort() (ЗакрытьПорт) - останавливает прослушивание порта LocalPort.
  7. NotifyPort(<Порт>, <Источник>, <Событие>, <Данные>) (ОповеститьПорт) - посылает оповещение клиенту, у которого открыт Порт. У клиента при этом срабатывает процедура ВнешнееСобытие(<Источник>, <Событие>, <Данные>). Источник, Событие, Данные - это параметры строкового типа, не более 1 Кб длины, т.е. максимум 1024 символа каждый. 
  8. Pause(<Миллисекунд>) (Пауза) - останавливает выполнение программы на некоторое время без нагрузки на процессор.
  9. Loopback(<ДвоичныеДанные>) (Петля) - достался по наследству. Метод принимает один аргумент типа ДвоичныеДанные и возвращает его копию.

   В моем случае пользователи 1С работают на терминальном сервере, т.е. IP всегда равен 127.0.0.1, поэтому не выводил IP как параметр в метод NotifyPort(), чтобы не усложнять.

   Работа компоненты тестировалась на платформах 1С: 8.3.12.1616 32бит, 8.3.13.1809 64бит, 8.3.15.1489 64бит. Операционные системы: Windows server 2008, Windows 8. В настоящее время проект по совместной работе пользователей в одном заказе полностью реализован и используется. 

Простой пример подключения и использования MyLib

  • Добавляем в конфигурацию общий макет:

В архив AddInNativeWin.zip включены 3 файла: AddInNativeWin32.dll, AddInNativeWin64.dll, MANIFEST.XML.

  • В модуле обычного приложения:

Объявляем глобальную переменную:

Перем MyLib Экспорт;

Находим процедуру ПриНачалеРаботыСистемы и вставляем туда код: 

	//Стартуем сервер взаимодействия
	Если ПодключитьВнешнююКомпоненту("ОбщийМакет.MyLib","MyLib",AddInType.Native) Тогда
		MyLib = Новый("AddIn.MyLib.CppNativeExtension");
		MyLib.LocalPort = МодульВзаимодействия.ПолучитьЛокальныйПорт();
		MyLib.PortTypeIsTCP = Истина;
		MyLib.OpenPort();
	Иначе
		Предупреждение("Компонента MyLib не подключена!");	
	КонецЕсли;	

В процедуре ПриЗавершенииРаботыСистемы вставляем код:

	//Останавливаем сервер взаимодействия
	Если MyLib <> Неопределено Тогда
		MyLib.ClosePort();
		MyLib = Неопределено;
	КонецЕсли;	
  • Добавляем в конфигурацию общий модуль МодульВзаимодействия (в свойствах ставим всего одну галочку "Сервер"):

//Данный алгоритм присвоения номера порта пользователю корректен только в том случае, если предположить, 
//что пользователи не будут открывать по несколько сеансов одной базы 1С:Предприятие под одним именем.
//В противном случае, придется разрабатывать более сложную систему назначения портов.
Функция ПолучитьЛокальныйПорт() Экспорт
	ЛокальныйПорт = 1024;
	ТекущийПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
	Для Каждого Соединение Из ПолучитьСоединенияИнформационнойБазы() Цикл
		Если Соединение.ИмяПриложения <> "Designer" И Соединение.ИмяПриложения <> "BackgroundJob" Тогда
			Если Соединение.Пользователь.УникальныйИдентификатор = ТекущийПользовательИБ.УникальныйИдентификатор Тогда
				ЛокальныйПорт = ЛокальныйПорт + Соединение.НомерСеанса;
			КонецЕсли;	
		КонецЕсли;		
	КонецЦикла;	
	Возврат ЛокальныйПорт;
КонецФункции

Функция ПолучитьСписокОткрытыхПортов() Экспорт
	ОткрытыеПорты = Новый Массив;
	ТекущийПользовательИБ = ПользователиИнформационнойБазы.ТекущийПользователь();
	Для Каждого Соединение Из ПолучитьСоединенияИнформационнойБазы() Цикл
		Если Соединение.ИмяПриложения <> "Designer" И Соединение.ИмяПриложения <> "BackgroundJob" Тогда
			Если Соединение.Пользователь.УникальныйИдентификатор <> ТекущийПользовательИБ.УникальныйИдентификатор Тогда
				ОткрытыеПорты.Добавить(1024 + Соединение.НомерСеанса);
			КонецЕсли;	
		КонецЕсли;		
	КонецЦикла;	
	Возврат ОткрытыеПорты;
КонецФункции	

Процедура ОповеститьВсех(Событие,Данные,Источник) Экспорт
	Для Каждого Порт Из ПолучитьСписокОткрытыхПортов() Цикл
		MyLib.NotifyPort(Порт,"MyLib.Port: " + MyLib.LocalPort,Событие,Данные);
	КонецЦикла;
	Оповестить(Событие,Данные,Источник); //На случай, если требуется оповещение самому себе
КонецПроцедуры
  • В форме документа ЗаказПокупателя:

Ищем обработчик ПослеЗаписи и прописываем там код:

	МодульВзаимодействия.ОповеститьВсех("OrderRecord",Строка(Ссылка.УникальныйИдентификатор()),ЭтаФорма);

Добавляем новую процедуру:

Процедура ОбработкаОповещенияВзаимодействия(Источник, Событие, Данные)
	Если Событие = "OrderRecord" Тогда
		ЭтотОбъект.Прочитать();
		ЭтаФорма.Обновить();
		ОбновлениеОтображения();
		Предупреждение("Форма обновлена!");
	КонецЕсли;	
КонецПроцедуры	

В обработчик ВнешнееСобытие вставляем код:

	Если Лев(Источник,5) = "MyLib" Тогда
		ОбработкаОповещенияВзаимодействия(Источник, Событие, Данные);
		Возврат;
	КонецЕсли;

В обработчик ОбработкаОповещения прописываем:

	ОбработкаОповещенияВзаимодействия(Источник, ИмяСобытия, Параметр);

 

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

   Исходный код MyLib также выкладываю. Возможно, кто-то захочет его использовать как базу для своей внешней компоненты.

   На этом пока все.

hative внешняя компонента udp tcp взаимодействие оповещение событие dll

См. также

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

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

4440 руб.

22.06.2020    18133    18    33    

22

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

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

2400 руб.

04.05.2018    46803    122    66    

66

Разработка внешних компонент Программист Платформа 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    28234    138    100    

90

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

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

4600 руб.

27.06.2023    3399    2    0    

4

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

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

1500 руб.

17.09.2018    36484    113    127    

114

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

Некоторые практические аспекты создания внешних компонент на языке С++ для платформы 1С 8.3++.

26.01.2024    6791    starik-2005    32    

44

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

Пример взаимодействия 1С с Apach Kafka посредством внешней компоненты, разработанной на основе официальной библиотеки librdkafka (the Apache Kafka C/C++ client library).

22.11.2023    4378    87    ivan1703    26    

41
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. acanta 06.10.19 00:26 Сейчас в теме
Правильно ли я понимаю, что пауза в вашей компоненте может быть использована как аналог модального вопроса ?
2. vdv2701 91 06.10.19 04:33 Сейчас в теме
Да, правильно. Если на клиенте включить паузу, то определенное время интерфейс пользователя будет заблокирован.
3. gorenski 363 07.10.19 05:45 Сейчас в теме
Хорошая штука, из минусов - разве что название MyLib не отражает сути ))
4. serpent 69 07.10.19 11:00 Сейчас в теме
А для работы на НЕ терминальном сервере? наверное не подойдет?
Нужен IP в метод NotifyPort() ??
5. vdv2701 91 07.10.19 17:17 Сейчас в теме
Да, если работа с базой 1С идет по локальной сети, например, а не в терминале, то метод NotifyPort() нужно доработать. Исходники есть, доработки несложные, добавить параметр IP.
6. EVKash 16 10.10.19 08:28 Сейчас в теме
(5) Из минусов видится, что если вдруг порт занят, то мы увидим просто "Компонента MyLib не подключена!".
Не очень хорошо делать жесткую привязку к сеансу.
Кстати... что вернет MyLib.OpenPort() в таком случае? Ошибку?
И открытые порты я бы куда-нибудь в РС записывал. При подключении - обновлять.
Из пожеланий - доработать под разные IP...
7. vdv2701 91 10.10.19 11:19 Сейчас в теме
Этот механизм назначения портов около 3 недель на рабочей базе, пока проблем не было, буду решать по мере поступления. Обычно служебные порты не превышают 1024, поэтому вероятность пересечения с каким-то служебным портом очень мала. Остальные ограничения этого механизма описаны в статье.
Да, если порт занят, то MyLib.OpenPort() в свойстве компоненты Status вернет номер ошибки, но в статье этот случай не рассматривается.
8. Cyberhawk 135 30.10.19 13:06 Сейчас в теме
(7)
вероятность пересечения с каким-то служебным портом очень мала
Учитывая, что:
- номер сеанса в большинстве типовых инфобаз через доволно короткое время начинает измеряться сотнями, тысячами и десятками тысяч
- кластер в типовом исполнении занимает порты 1540-1591
- количество портов ограничено 2^16 (максимальный номер, таким образом, равен 65535)
, то конфликты и сюрпризы неизбежны.
Каждый порт-кандидат рекомендуется запрашивать у самой ОС, тогда она гарантированно выдаст валидный и незанятый.
9. vdv2701 91 30.10.19 14:35 Сейчас в теме
Пока не сталкивался с такими сюрпризами. Этот механизм нормально работает уже более месяца. Возможно, если будут еще внедрения, и какие-то конфликты появятся, то буду что-то придумывать.
10. bavkyz 4 25.11.19 18:51 Сейчас в теме
Хорошая статья про Native внешняя компонента, я добавил параметр ip-адрес, как и писал автор - это не сложно, но мне потребовалось около 8 часов, т.к. я не знаю c++.
11. dablack 09.02.20 12:43 Сейчас в теме
(10) может поделитесь с сообществом чтобы не тратить 8 часов ?
12. bavkyz 4 17.02.20 09:36 Сейчас в теме
(11) Извиняюсь за долгий ответ. Если АВТОР не будет против могу дать ссылку на гит.
14. Yulka_Pentagramma 26.02.20 23:28 Сейчас в теме
(12) и мне, пожалуйста, ссылку на гит. Никак не могу настроить оповещение пользователю при создании новой заявки. Сервер взаимодействия мне не по карману... да и 1 стартани нет... пробовала купить подписку, почему то в 40 тысяч выходит 😢

Готова выучить си, чтобы настроить эту систему оповещений
26. arti4k 13.05.20 17:16 Сейчас в теме
(10) а где посмотреть куда ip - адрес добавили?
13. vdv2701 91 17.02.20 13:19 Сейчас в теме
Автор не против
dablack; BigB; +2 Ответить
15. bavkyz 4 27.02.20 06:28 Сейчас в теме
16. bavkyz 4 27.02.20 06:35 Сейчас в теме
Гит ссылку проверяют модераторы, там же есть скомпилированные dll, маленький код - IP как параметр:
	ЛокальныйIP = дюк_Network.ПолучитьЛокальныйIP();
		Если ЛокальныйIP = ВыборкаДетальныеЗаписи.ip Тогда
			LocalIP = "127.0.0.1";
		Иначе	
			LocalIP = ВыборкаДетальныеЗаписи.ip;
		Конецесли;	
		дюк_NativeApi.ОповеститьПользователя("Входящий вызов",НомерАбонента,LocalIP,ВыборкаДетальныеЗаписи.Порт);
akR00b; Yulka_Pentagramma; +2 Ответить
17. bavkyz 4 28.02.20 18:43 Сейчас в теме
Кто воспользовался гитом, все получилось?
Yulka_Pentagramma; +1 Ответить
18. Yulka_Pentagramma 01.03.20 11:55 Сейчас в теме
(17) Спасибо Огромнейшее!!!, получилось)

Осталось разобраться как это работает)))
31. jdan 9 05.11.20 08:39 Сейчас в теме
(17Добрый день!
Не могли бы уточнить как использовать параметр IP , где его нужно добавить на примере:

MyLib.NotifyPort(Порт,"MyLib.Port: " + MyLib.LocalPort,Событие,Данные);
Спасибо!
19. Yulka_Pentagramma 01.03.20 14:13 Сейчас в теме
Подскажите пожалуйста... скачала Вашу компоненту, пытаюсь настроить. Плохо получается... Платформа 6.3.16.1063.

Находим процедуру ПриНачалеРаботыСистемы и вставляем туда код...

Вставила.


Добавляем в конфигурацию общий модуль МодульВзаимодействия (в свойствах ставим всего одну галочку "Сервер"):

Добавила.

но, ПриНачалеРаботыСистемы - это на клиенте, а МодульВзаимодействия - на сервере. из ПриНачалеРаботыСистемы - не могу обратиться к МодульВзаимодействия. А если доставить галку "Клиент", Тогда пользователей базы не вижу... вынести их в отдельную функцию?
20. Yulka_Pentagramma 01.03.20 14:26 Сейчас в теме
перенесла в процедуру ПередНачаломРаботыСистемы - всё работает. Только из общего модуля МодульВзаимодействия не видно переменной MyLib...
21. vdv2701 91 01.03.20 17:40 Сейчас в теме
Постараюсь подготовить в ближайшее время реализацию примера из публикации, чтобы небыло недопониманий.
22. vdv2701 91 01.03.20 18:25 Сейчас в теме
(20) Простенький пример из публикации реализовал, базу прикрепляю. Еще раз все проверил, работает. Нашел 2 небольших ошибки в примере, поэтому подкорректировал публикацию.

Было:
Если Соединение.ИмяПриложения <> "Designer" Тогда


Стало:
Если Соединение.ИмяПриложения <> "Designer" И Соединение.ИмяПриложения <> "BackgroundJob" Тогда


BackgroundJob - это фоновый сеанс, который автоматически стартует на новых версиях платформы.

Если будут вопросы, пишите.
Прикрепленные файлы:
ПодсистемаВзаимодействия.dt
Yulka_Pentagramma; +1 Ответить
23. Yulka_Pentagramma 01.03.20 20:43 Сейчас в теме
Спасибо большое!

Только я тут поняла, что у меня УФ, поэтому я не могу добраться до переменной MyLib... вроде переделок под УФ не много, попробую, чем черт не шутит, может получится)))
24. vdv2701 91 02.03.20 07:30 Сейчас в теме
(23) Для управляемых форм есть типовая "СистемаВзаимодействия".
Вы наверное невнимательно читали публикацию, писал уже про нее. На инфостарте можете найти дополнительную информацию по применению этой системы, зачем изобретать велосипед.
25. Yulka_Pentagramma 02.03.20 12:35 Сейчас в теме
(24) я внимательно читала, просто СистемаВзаимодействия мне не по карману. Вот и выкручиваюсь...
29. jdan 9 05.11.20 07:02 Сейчас в теме
(25)Извините пож. у Вас получилось реализовать на УФ ?
30. Yulka_Pentagramma 05.11.20 08:27 Сейчас в теме
(29) здравствуйте. Система взаимодействия оказалась бесплатной. С её помощью я оповещаю клиента о событиях сервера. И даже чат работает)
rolin555; +1 Ответить
34. MikhailDr 02.06.21 08:06 Сейчас в теме
(30) Она бесплатна? Где вы ее взяли? Или у вас КОРП?
27. QuirkyKot 10 03.08.20 09:45 Сейчас в теме
Добрый день,
Данная компонента подойдет для мобильной платформы?
28. vdv2701 91 04.08.20 08:57 Сейчас в теме
(27) На мобильной платформе не тестировалась компонента. Если есть желание, то в комментариях выложили уже ссылку на Гит, можете потестировать бесплатно. Отпишитесь потом пожалуйста, как все прошло.
32. MikhailDr 01.06.21 16:21 Сейчас в теме
Подскажите пожалуйста. У меня стоит задача:

С сайта приходит сообщение с идентификатором документа, именем пользователя который отправил сообщение и именем компьютера на котором он это сделал. Мне необходимо после прихода сообщения открыть форму документа на том компьютере и у того пользователя, который отправил сообщение с сервера.

Я могу решить эту задачу с помощью вашей компоненты?
33. vdv2701 91 01.06.21 23:08 Сейчас в теме
35. MikhailDr 02.06.21 08:11 Сейчас в теме
(33) Я не сразу заметил, компонента под обычные формы. У меня УФ. Подскажите под УФ надо саму компоненту менять? Я в c++ не разбираюсь, доработать саму компоненту не смогу.
36. vdv2701 91 03.06.21 00:10 Сейчас в теме
Методика написания внешних компонент не зависит от того, в каких формах эта компонента будет использоваться: в управляемых или обычных. Поэтому переписывать код компоненты под управляемые формы нет смысла. У вас изменится только методика подключения компоненты в управляемых формах.
37. MikhailDr 03.06.21 11:39 Сейчас в теме
38. 4361fmv 69 30.10.21 10:51 Сейчас в теме
Добрый день.
Поддержу вопрос. Где указывается IP адрес. В примере по ссылке не нашел!

Спасибо
39. 4361fmv 69 30.10.21 10:52 Сейчас в теме
40. vdv2701 91 23.11.21 10:11 Сейчас в теме
Это вопрос к автору ссылки GIT, т.е. к bavkyz.
Оставьте свое сообщение