Подойдет пример на Delphi C++, но разберусь с любым языком. Важно только какие параметры передавать.
Просьба дочитать текст вопроса до конца или не отвечать вовсе.
В моей программе встроена поддержка скриптов Microsoft ® Windows Script Host, которые работают через механизм OLE Automation (этот момент определяющий).
Запускается все это стандартно:
ScriptControl := CreateOLEObject('MSScriptControl.ScriptControl');
with (ScriptControl as IScriptControl) do begin
Language := 'VBScript';
Script.ExecuteStatement(" ...
где IScriptControl импортируетс из MSScriptControl_TLB C:\Windows\system32\msscript.ocx
и IWshShell3 (WScript.Shell) подтягивается из "IWshRuntimeLibrary", файла wshom.ocx
Как Вам известно, в скриптах запускаемых интерпретатором wscript.exe из файлов объект "WScript" обладает замечательным методом CreateObject. Этот метод выполняет две задачи: создает объект "WbemScripting.SWbemSink" и привязывает к его событиям процедуры из сценария (скрипта).
Грубо говоря, следующий код создает объект objSink и устанавливает его свойству OnObjectReady процедуру Sink_OnObjectReady. Далее процедура Sink_OnObjectReady может быть задействована в асинхронном вызове.
Set objSink = WScript.CreateObject("WbemScripting.SWbemSink", "Sink_")
Sub Sink_OnObjectReady(OutParams, objAsyncContext)
End Sub
В режиме OLE Automation метода WScript.CreateObject (как и много чего еще). Но её можно написать в основном теле программы из которой выполняется скрипт и добавить в скрипт.
Подобная функция написана в autoit
"ObjEvent" - Обрабатывает поступающие события от указанного объекта.
Решение этой задачи на autoit выглядит так:
$Sink = ObjCreate("WbemScripting.SWbemSink")
ObjEvent($Sink , "SINK_")
Func SINK_OnObjectReady($objEvent, $objAsyncContext)
EndFunc
Собственно в чем затык с Windows Script Host:
В основной программе через ScriptControl.Procedures.Item[N] доступна любая процедура в виде IScriptProcedure = interface(IDispatch)
В самом скрипте есть доступ к IDispatch процедуры через штатную функцию GetRef("Sink_OnObjectReady")
Но похоже этот IDispatch надо установить в недоступное для редактирование свойство через вызов Invoke. Приведу отрывок WbemScripting_TLB, который меня к этому заключению привел:
unit WbemScripting_TLB;
...
// *********************************************************************//
// Interface: ISWbemSink
// Flags: (4560) Hidden Dual NonExtensible OleAutomation Dispatchable
// GUID: {75718C9F-F029-11D1-A1AC-00C04FB6C223}
// *********************************************************************//
ISWbemSink = interface(IDispatch)
['{75718C9F-F029-11D1-A1AC-00C04FB6C223}']
procedure Cancel; safecall;
end;
...
// *********************************************************************//
// DispIntf: ISWbemSinkEvents
// Flags: (4240) Hidden NonExtensible Dispatchable
// GUID: {75718CA0-F029-11D1-A1AC-00C04FB6C223}
// *********************************************************************//
ISWbemSinkEvents = dispinterface
['{75718CA0-F029-11D1-A1AC-00C04FB6C223}']
procedure OnObjectReady(const objWbemObject: ISWbemObject;
const objWbemAsyncContext: ISWbemNamedValueSet); dispid 1;
procedure OnCompleted(iHResult: WbemErrorEnum; const objWbemErrorObject: ISWbemObject;
const objWbemAsyncContext: ISWbemNamedValueSet); dispid 2;
procedure OnProgress(iUpperBound: Integer; iCurrent: Integer; const strMessage: WideString;
const objWbemAsyncContext: ISWbemNamedValueSet); dispid 3;
procedure OnObjectPut(const objWbemObjectPath: ISWbemObjectPath;
const objWbemAsyncContext: ISWbemNamedValueSet); dispid 4;
end;
...
Кроме autoit эта задача решена ещё как минимум в 1 проекте, но они, увы, без исходных кодов.