WMI技术介绍和应用——Event Consumer Provider
? ? ? ? 在《WMI技術(shù)介紹和應(yīng)用——Event Provider》和《WMI技術(shù)介紹和應(yīng)用——接收事件》中,我們展現(xiàn)了如何處理和事件相關(guān)的WMI知識(shí)。而《WMI技術(shù)介紹和應(yīng)用——接收事件》一文則主要講解了如何查詢事件,這種查詢是在我們進(jìn)程存在時(shí)發(fā)生的,一旦我們進(jìn)程不存在了,這種查詢也無法執(zhí)行。我們將這種行為稱為消費(fèi)事件,我們執(zhí)行查詢的進(jìn)程叫做“事件臨時(shí)消費(fèi)者”。相對應(yīng)的,WMI還存在“事件永久消費(fèi)者”,它并不寄生我們的編寫的進(jìn)程中。本文主要講解“事件永久消費(fèi)者”的編寫方法。(轉(zhuǎn)載請指明出于breaksoftware的csdn博客)
? ? ? ? 由于VS2005沒有這種模板,所以我便使用事件提供者模板生成了一個(gè)工程,并對這個(gè)工程進(jìn)行改造。我們先從mof文件出發(fā)
? ? ? ? 由于我們不需要注冊事件提供者,所以我們刪除instance?of?__EventProviderRegistration內(nèi)容。
? ? ? ? 我們先要聲明一個(gè)事件消費(fèi)類
class TestEventConsumer : __EventConsumer
{[key] string name;[write] string value;
};
? ? ? ? 實(shí)例化該類
instance of TestEventConsumer as $Consumer
{name = "TestEventConsumer_Name1";value = "TestEventConsumer_Value";
};
? ? ? ? 再注冊一個(gè)事件消費(fèi)者提供者實(shí)例
instance of __EventConsumerProviderRegistration
{Provider = $EventConsumer;ConsumerClassNames = {"TestEventConsumer"};
};
? ? ? ? ConsumerClassNames是一個(gè)數(shù)組,它記錄了事件消費(fèi)者名。
? ? ? ? 然后要實(shí)例化一個(gè)篩選器
instance of __EventFilter as $Filter
{Name = "TestEventFilter";QueryLanguage = "WQL";Query = "SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_USBCOntrollerDevice'";EventNamespace = "\\\\.\\root\\CIMV2";
};
? ? ? ? 其中定義了篩選器的名字、查詢的語言、查詢的命令和需要查詢的命名空間。如果沒有指定EventNamespace,則使用該mof中默認(rèn)的命名空間。在本例中,我們要監(jiān)控USB設(shè)備的創(chuàng)建,故要監(jiān)控CIMV2空間。這兒需要注意的是,我們可以Query內(nèi)部事件或者外部事件。
? ? ? ? 最后我們將篩選器綁定到消費(fèi)者上。
instance of __FilterToConsumerBinding
{Consumer = $Consumer;Filter = $Filter;
};
? ? ? ? 如此,我們便將mof文件構(gòu)建好了。
? ? ? ? 我們再回到cpp文件中,我們首先要定義一個(gè)事件消費(fèi)者Sink
class CEventConsumerSink:public CComObjectRootEx<CComMultiThreadModel>,public IWbemUnboundObjectSink
{
public:CEventConsumerSink() {}~CEventConsumerSink(){}BEGIN_COM_MAP(CEventConsumerSink) COM_INTERFACE_ENTRY(IWbemUnboundObjectSink) END_COM_MAP() // IWbemUnboundObjectSink
public: STDMETHOD(IndicateToConsumer)(IWbemClassObject* pLogicalConsumer, long lNumObjects, IWbemClassObject** apObjects);
};
? ? ? ? 我們要實(shí)現(xiàn)IndicateToConsumer方法,將事件傳到到該方法中處理
STDMETHODIMP CEventConsumerSink::IndicateToConsumer(IWbemClassObject* pLogicalConsumer, long lNumObjects, IWbemClassObject** apObjects)
{ObjectLock lock(this); HRESULT hr = WBEM_S_NO_ERROR; CComVariant varClass; hr = pLogicalConsumer->Get(CComBSTR("__CLASS"), 0, &varClass, 0, 0);if (0 == _wcsicmp(V_BSTR(&varClass), L"TestEventConsumer")) {for (long lIndex = 0; lIndex < lNumObjects; lIndex++) {CComVariant varEventType;hr = apObjects[lIndex]->Get(CComBSTR("TargetInstance"), 0, &varEventType, 0, 0);CComQIPtr<IWbemClassObject> spEvent = V_UNKNOWN(&varEventType);CComVariant varEventTypeClass;hr = spEvent->Get(CComBSTR("__CLASS"), 0, &varEventTypeClass, 0, 0);OutputTrace("CEventConsumerSink::IndicateToConsumer"); } }else {hr = WBEM_E_NOT_FOUND;}return hr;
}
? ? ? ? 這段邏輯,我們獲取事件名稱,并檢測其是否是我們需要監(jiān)控的事件。如果是,則遍歷事件數(shù)組——發(fā)來的事件是一批的。
? ? ? ? 然后我們改造主類。事件消費(fèi)者提供者不需要繼承IWbemInstProviderImpl,但是要繼承IWbemEventConsumerProvider。于是我們在模板生成的代碼中將其他無關(guān)的方法去掉
class ATL_NO_VTABLE CEventConsumer : public CComObjectRootEx<CComMultiThreadModel>,public CComCoClass<CEventConsumer, &CLSID_EventConsumer>,public IWbemProviderInit,public IWbemEventConsumerProvider
{ public:CEventConsumer(){ }~CEventConsumer(){}DECLARE_REGISTRY_RESOURCEID(IDR_EVENTCONSUMER)DECLARE_NOT_AGGREGATABLE(CEventConsumer)BEGIN_COM_MAP(CEventConsumer)COM_INTERFACE_ENTRY(IWbemProviderInit)COM_INTERFACE_ENTRY(IWbemEventConsumerProvider)END_COM_MAP()//IWbemProviderInitHRESULT STDMETHODCALLTYPE Initialize( __in_opt LPWSTR pszUser,LONG lFlags,__in LPWSTR pszNamespace,__in_opt LPWSTR pszLocale,IWbemServices *pNamespace,IWbemContext *pCtx,IWbemProviderInitSink *pInitSink);// IWbemEventConsumerProviderHRESULT STDMETHODCALLTYPE FindConsumer( /* [in] */ IWbemClassObject *pLogicalConsumer,/* [out] */ IWbemUnboundObjectSink **ppConsumer);};
? ? ? ??Initialize中刪除模板生成的多余代碼就可以了,我們主要要實(shí)現(xiàn)的就是FindConsumer方法
STDMETHODIMP CEventConsumer::FindConsumer( /* [in] */ IWbemClassObject *pLogicalConsumer,/* [out] */ IWbemUnboundObjectSink **ppConsumer)
{HRESULT hr = WBEM_E_NOT_FOUND;*ppConsumer = NULL;CComVariant varClass;hr = pLogicalConsumer->Get(L"__Class", 0, &varClass, 0, 0);if (0 == _wcsicmp(V_BSTR(&varClass), L"TestEventConsumer")) {CComObject<CEventConsumerSink>* pEventSink = NULL;hr = CComObject<CEventConsumerSink>::CreateInstance(&pEventSink);if (FAILED(hr)) {return hr;}hr = pEventSink->QueryInterface(IID_IWbemUnboundObjectSink, (LPVOID*)ppConsumer);if (FAILED(hr)) {return hr;}}else {hr = WBEM_E_NOT_FOUND;}return hr;
}
? ? ? ? 這段邏輯我們在檢測完消費(fèi)者類是否正確后,就去獲取消費(fèi)者指針。
? ? ? ? 如此Event Consumer Provider便搭建起來了。
總結(jié)
以上是生活随笔為你收集整理的WMI技术介绍和应用——Event Consumer Provider的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WMI技术介绍和应用——Event Pr
- 下一篇: WMI技术介绍和应用——总结(完)