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

01.03.20

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

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

Скачать файлы

Наименование Файл Версия Размер
Внешняя компонента MyLib
.zip 804,28Kb
24
.zip 804,28Kb 24 Скачать
Внешняя компонента MyLib с исходным кодом
.zip 26,15Mb
28
.zip 26,15Mb 28 Скачать

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

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

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

См. также

Медиадисплей. Рекламный информационный монитор для покупателя.

Разработка внешних компонент 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 и маркетинг Управленческий учет Платные (руб)

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

16800 руб.

30.05.2017    52100    34    69    

43

Внешняя компонента для сканирования (замена TWAIN-компоненты БСП) (Native Win 32/64)

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

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

2400 руб.

12.05.2020    26243    131    99    

83

Внешняя компонента для подключения 1С к телефонии Asterisk

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

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

2400 руб.

04.05.2018    44974    117    64    

60

Внешняя компонента печати PDF (Native Win 32/64)

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

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

1500 руб.

17.09.2018    35078    104    123    

111

Мастер создания внешних компонент 1С (технология COM) для DELPHI 6/7/8/2005/2006/2007/2008/2010/XE/XE2/XE3

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

Средство для сверхбыстрой разработки внешних компонент 1С:Предприятия 7.7 и 8 по технологии COM на всех версиях DELPHI, начиная с 6.

2000 руб.

28.03.2013    53999    35    14    

68

QR-код с логотипом компании (обычная и управляемая форма)

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

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

2400 руб.

22.06.2016    30839    4    4    

8

Внешняя компонента 1С и С++. Продолжаем разговор.

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

А давайте запилим 8.3.26 до релиза, или оповещение с сервера...

19.02.2024    4039    starik-2005    28    

52

Внешние компоненты 1С и язык C++

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

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

26.01.2024    4778    starik-2005    32    

39
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. acanta 06.10.19 00:26 Сейчас в теме
Правильно ли я понимаю, что пауза в вашей компоненте может быть использована как аналог модального вопроса ?
2. vdv2701 91 06.10.19 04:33 Сейчас в теме
Да, правильно. Если на клиенте включить паузу, то определенное время интерфейс пользователя будет заблокирован.
3. gorenski 372 07.10.19 05:45 Сейчас в теме
Хорошая штука, из минусов - разве что название MyLib не отражает сути ))
4. serpent 67 07.10.19 11:00 Сейчас в теме
А для работы на НЕ терминальном сервере? наверное не подойдет?
Нужен IP в метод NotifyPort() ??
5. vdv2701 91 07.10.19 17:17 Сейчас в теме
Да, если работа с базой 1С идет по локальной сети, например, а не в терминале, то метод NotifyPort() нужно доработать. Исходники есть, доработки несложные, добавить параметр IP.
6. EVKash 14 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 3 25.11.19 18:51 Сейчас в теме
Хорошая статья про Native внешняя компонента, я добавил параметр ip-адрес, как и писал автор - это не сложно, но мне потребовалось около 8 часов, т.к. я не знаю c++.
11. dablack 09.02.20 12:43 Сейчас в теме
(10) может поделитесь с сообществом чтобы не тратить 8 часов ?
12. bavkyz 3 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 3 27.02.20 06:28 Сейчас в теме
16. bavkyz 3 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 3 28.02.20 18:43 Сейчас в теме
Кто воспользовался гитом, все получилось?
Yulka_Pentagramma; +1 Ответить
18. Yulka_Pentagramma 01.03.20 11:55 Сейчас в теме
(17) Спасибо Огромнейшее!!!, получилось)

Осталось разобраться как это работает)))
31. jdan 8 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 8 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 64 30.10.21 10:51 Сейчас в теме
Добрый день.
Поддержу вопрос. Где указывается IP адрес. В примере по ссылке не нашел!

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