EventProxy — внешняя компонента для асинхронной обработки событий COM-объектов (работает в 7.7 и 8.0)

EventProxy — внешняя компонента для асинхронной обработки событий COM-объектов.
Работает в 7.7 и в 8.0

Содержит единственный объект EventProxy.

Свойства:

  • ГлубинаБуфераСобытий(EventBufferDepth) — глубина буфера событий интерфейса IAsyncEvent
  • ГлобальныйКонтекст(GlobalContext) — собственно он и есть

Методы:

  • Источник (Source) Устанавливает источник событий.
    параметры:
    • Источник — собственно источник событий.
    • ProgID — ProgID источника (По этому ProgID определяются DISPID и имена событий)
    • ИмяИсточника — имя источника событий, как оно будет передано в процедуру ОбработкаВнешнегоСобытия
  • ПолучитьОбъект (GetObject)
    передает свой единственный параметр в ф-ю CoGetObject и возвращает полученный объект (аналог GetObject в VB)
  • Сериализовать
    сериализует переданный параметр при помощи ObjRefMoniker

При вызове метода «Источник», EventProxy подписывается на события источника.
При получении события оно передается в 1С через IAsyncEvent.

В процедуре ОбработкаВнешнегоСобытия(Источник, Событие, Данные) аргумент «Данные» содержит сериализованный список значений с параметрами события. Для десериализации параметров события необходимо вызвать функцию ЗначениеИзСтрокиВнутр(Данные). Параметры с типом VT_DISPATCH сериализуются при помощи ObjRefMoniker и могут быть десериализованы методом «ПолучитьОбъект».

Поскольку обработка событий в 1С идет в асинхронном режиме, следует соблюдать осторожность при использовании параметров, восстановленных из ссылки ObjRef, т.к. к тому времени, когда у 1С появится время обработать внешнее событие, объект может прекратить свое существование.

Пример использования:

Перем Обработчик, ОбработчикСобытий,objWMIServices;

Процедура ПриНачалеРаботыСистемы()
//ПодключитьВнешнююКомпоненту("Addin.EventProxy");
ЗагрузитьВнешнююКомпоненту(КаталогИБ()+"EventProxy.dll");
ОбработчикСобытий=СоздатьОбъект("Addin.EventProxy");
ОбработчикСобытий.ГлубинаБуфераСобытий=200;
Обработчик=СоздатьОбъект("WbemScripting.SWbemSink");
ОбработчикСобытий.Источник(Обработчик,"WbemScripting.SWbemSink","WMISink");
objWMIServices = ОбработчикСобытий.ПолучитьОбъект( "winmgmts:{impersonationLevel=impersonate}!\.
ootCIMV2");
Shell=СоздатьОбъект("WScript.Shell");
Env=Shell.Environment("Process");
objWMIServices.ExecNotificationQueryAsync(Обработчик,
"SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_PrintJob'
|AND TargetInstance.Owner='"+Env.Item("UserName")+"'");
КонецПроцедуры // ПриОткрытии

Процедура ОбработкаВнешнегоСобытия(Источник, Событие, Данные)
Если (Источник="WMISink") и (Событие="OnObjectReady") Тогда
Д=ЗначениеИзСтрокиВнутр(Данные);
WMIObj=ОбработчикСобытий.ПолучитьОбъект(Д.ПолучитьЗначение(1));
ИмяСобытия=WMIObj.SystemProperties_.Item("__Class").Value;
Job=WMIObj.TargetInstance;
Если ИмяСобытия="__InstanceDeletionEvent" Тогда
Если Job.PagesPrinted=Job.TotalPages Тогда
Сообщить("Документ "+Job.Document+" напечатан");
Иначе
Сообщить("Документ "+Job.Document+" не напечатан","!!!");
КонецЕсли;
КонецЕсли;
Сообщить("Name:"+Job.Name);
Сообщить("Caption:"+Job.Caption);
Сообщить("Description:"+Job.Description);
Сообщить("Document:"+Job.Document);
Сообщить("Owner:"+Job.Owner);
Сообщить("TotalPages:"+Job.TotalPages);
Сообщить("StartTime:"+Job.StartTime);
Сообщить("HostPrintQueue:"+Job.HostPrintQueue);
Сообщить("JobStatus:"+Job.JobStatus);
Сообщить("Size:"+Job.Size);
Сообщить("Status:"+Job.Status);
Сообщить("StatusMask:"+Job.StatusMask);
Сообщить("PagesPrinted:"+Job.PagesPrinted);
Сообщить("JobId:"+Job.JobId);
КонецЕсли;
КонецПроцедуры // ОбработкаВнешнегоСобытия

8 Comments

  1. steban

    С аутглюком пример получился неудачный — очень часто к моменту обработки события ссылка на письмо становится инвалидной.

    Заменил на отслеживание событий очереди принтера через WMI.

    Reply ↓
  2. steban

    При вызове метода Источник создается происходит подписка на события.

    Обработка событий происходит в процедуре ОбработкаВнешнегоСобытия, где Источник-имя заданное при подписке (чтобы различать источники), Событие — наименование события, как оно прописано в TypeLibrary источника, данные — список значений с параметрами события, сериализованный методом, аналогичным ЗначениеВСтрокуВнутр.

    Параметры с типом VT_DISPATCH надо дополнительно десериализовать методом ПолучитьОбъект (GetObject).

    Могу набросать пример по отслеживанию событий файловой системы.

    Reply ↓
  3. Abadonna

    за идею +1

    Reply ↓
  4. sumerian

    прикрутил для отслеживания появления в папке файлов. работает, но wmiprvse.exe отжирает до 60% процессорного времени, после ОбработчикСобытий=0 и Обработчик=0 процесс не исчезает. убиваешь в диспетчере задач — сам поднимается и опять жреть. есть решение?

    Reply ↓
  5. steban

    2 sumerian:

    решение есть — увеличить polling interval.

    Код
    within 10

    Показать полностью

    Reply ↓
  6. steban

    Добавлена поддержка объектов, не реализующих IProvideClassInfo (например InternetExplorer.Application )

    Reply ↓
  7. German

    А как использовать с ADODB.Connection?

    Код
          
    ОбработчикСобытий=Новый ("Addin.EventProxy");
    ОбработчикСобытий.ГлубинаБуфераСобытий=200;
    Обработчик= Новый COMОбъект("ADODB.Connection");
    Обработчик.ConnectionString = СтрокаПодключения;
    Обработчик.ConnectionTimeout=0;
    Обработчик.CursorLocation=3;
    Обработчик.Open();
    ОбработчикСобытий.Источник(Обработчик,"ADODB.Connection","ADO");
    АсинхронныйОбъект=ОбработчикСобытий.ПолучитьОбъект(" "); 

    Показать полностью

    Что передать в функцию ПолучитьОбъект чтобы вернуть объект?

    Reply ↓
  8. steban

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *