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 не будет опубликован. Обязательные поля помечены *