Beispiel: Empfangen von Ereignisbenachrichtigungen über WMI
Sie können das Verfahren und das Codebeispiel in diesem Thema verwenden, um die WMI-Clientanwendung abzuschließen, die COM-Initialisierung durchführt, eine Verbindung mit WMI auf dem lokalen Computer herstellt, eine Ereignisbenachrichtigung empfängt und anschließend bereinigt wird. Im Beispiel wird der Benutzer eines Ereignisses benachrichtigt, wenn ein neuer Prozess erstellt wird. Die Ereignisse werden asynchron empfangen.
Das folgende Verfahren wird verwendet, um die WMI-Anwendung auszuführen. Die Schritte 1 bis 5 enthalten alle Schritte, die zum Einrichten und Herstellen einer Verbindung mit WMI erforderlich sind, und Schritt 6 ist der Ort, an dem die Ereignisbenachrichtigungen empfangen werden.
So empfangen Sie eine Ereignisbenachrichtigung über WMI-
Initialisieren Sie COM-Parameter mit einem Aufruf von CoInitializeEx.
Weitere Informationen finden Sie unter Initialisieren von COM für eine WMI-Anwendung.
Initialisieren Sie die COM-Prozesssicherheit, indem Sie CoInitializeSecurityaufrufen.
Weitere Informationen finden Sie unter Festlegen der Standardmäßigen Prozesssicherheitsstufe mit C++-.
Rufen Sie den anfänglichen Locator an WMI ab, indem Sie CoCreateInstanceaufrufen.
Weitere Informationen finden Sie unter Erstellen einer Verbindung mit einem WMI-Namespace.
Rufen Sie einen Zeiger auf IWbemServices für den Namespace root\cimv2 auf dem lokalen Computer ab, indem Sie IWbemLocator::ConnectServeraufrufen. Informationen zum Herstellen einer Verbindung mit einem Remotecomputer finden Sie unter Beispiel: Abrufen von WMI-Daten von einem Remotecomputer.
Weitere Informationen finden Sie unter Erstellen einer Verbindung mit einem WMI-Namespace.
Legen Sie IWbemServices Proxysicherheit fest, damit der WMI-Dienst den Client durch Aufrufen CoSetProxyBlanketidentitätswechseln kann.
Weitere Informationen finden Sie unter Festlegen der Sicherheitsstufen für eine WMI-Verbindung.
Verwenden Sie den IWbemServices Zeiger, um Anforderungen an WMI zu stellen. In diesem Beispiel wird die IWbemServices::ExecNotificationQueryAsync Methode verwendet, um asynchrone Ereignisse zu empfangen. Wenn Sie asynchrone Ereignisse empfangen, müssen Sie eine Implementierung von IWbemObjectSink-bereitstellen. In diesem Beispiel wird die Implementierung in der EventSink-Klasse bereitgestellt. Der Implementierungscode und der Headerdateicode für diese Klasse werden unterhalb des Hauptbeispiels bereitgestellt. Die IWbemServices::ExecNotificationQueryAsync Methode ruft die EventSink::Indicate-Methode auf, wenn ein Ereignis empfangen wird. In diesem Beispiel wird die EventSink::Indicate-Methode immer aufgerufen, wenn ein Prozess erstellt wird. Führen Sie zum Testen dieses Beispiels den Code aus, und starten Sie einen Prozess wie Notepad.exe. Dadurch wird eine Ereignisbenachrichtigung ausgelöst.
Weitere Informationen zum Erstellen von Anforderungen von WMI finden Sie unter Bearbeiten von Klassen- und Instanzinformationen und Aufrufen einer Methode.
Der folgende Beispielcode empfängt Ereignisbenachrichtigungen über WMI.
#include "eventsink.h"
int main(int iArgCnt, char ** argv)
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM negotiates service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object. "
<< "Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: ---------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the local root\cimv2 namespace
// and obtain pointer pSvc to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 6: -------------------------------------------------
// Receive event notifications -----------------------------
// Use an unsecured apartment for security
IUnsecuredApartment* pUnsecApp = NULL;
hres = CoCreateInstance(CLSID_UnsecuredApartment, NULL,
CLSCTX_LOCAL_SERVER, IID_IUnsecuredApartment,
(void**)&pUnsecApp);
EventSink* pSink = new EventSink;
pSink->AddRef();
IUnknown* pStubUnk = NULL;
pUnsecApp->CreateObjectStub(pSink, &pStubUnk);
IWbemObjectSink* pStubSink = NULL;
pStubUnk->QueryInterface(IID_IWbemObjectSink,
(void **) &pStubSink);
// The ExecNotificationQueryAsync method will call
// The EventQuery::Indicate method when an event occurs
hres = pSvc->ExecNotificationQueryAsync(
_bstr_t("WQL"),
_bstr_t("SELECT * "
"FROM __InstanceCreationEvent WITHIN 1 "
"WHERE TargetInstance ISA 'Win32_Process'"),
WBEM_FLAG_SEND_STATUS,
NULL,
pStubSink);
// Check for errors.
if (FAILED(hres))
{
printf("ExecNotificationQueryAsync failed "
"with = 0x%X\n", hres);
pSvc->Release();
pLoc->Release();
pUnsecApp->Release();
pStubUnk->Release();
pSink->Release();
pStubSink->Release();
CoUninitialize();
return 1;
}
// Wait for the event
Sleep(10000);
hres = pSvc->CancelAsyncCall(pStubSink);
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pUnsecApp->Release();
pStubUnk->Release();
pSink->Release();
pStubSink->Release();
CoUninitialize();
return 0; // Program successfully completed.
}
Die folgende Headerdatei wird für die Klasse EventSink verwendet. Die EventSink-Klasse wird im vorherigen Codebeispiel verwendet.
// EventSink.h
#ifndef EVENTSINK_H
#define EVENTSINK_H
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
class EventSink : public IWbemObjectSink
{
LONG m_lRef;
bool bDone;
public:
EventSink() { m_lRef = 0; }
~EventSink() { bDone = true; }
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
virtual HRESULT
STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv);
virtual HRESULT STDMETHODCALLTYPE Indicate(
LONG lObjectCount,
IWbemClassObject __RPC_FAR *__RPC_FAR *apObjArray
);
virtual HRESULT STDMETHODCALLTYPE SetStatus(
/* [in] */ LONG lFlags,
/* [in] */ HRESULT hResult,
/* [in] */ BSTR strParam,
/* [in] */ IWbemClassObject __RPC_FAR *pObjParam
);
};
#endif // end of EventSink.h
Der folgende Beispielcode ist eine Implementierung der EventSink-Klasse.
// EventSink.cpp
#include "eventsink.h"
ULONG EventSink::AddRef()
{
return InterlockedIncrement(&m_lRef);
}
ULONG EventSink::Release()
{
LONG lRef = InterlockedDecrement(&m_lRef);
if(lRef == 0)
delete this;
return lRef;
}
HRESULT EventSink::QueryInterface(REFIID riid, void** ppv)
{
if (riid == IID_IUnknown || riid == IID_IWbemObjectSink)
{
*ppv = (IWbemObjectSink *) this;
AddRef();
return WBEM_S_NO_ERROR;
}
else return E_NOINTERFACE;
}
HRESULT EventSink::Indicate(long lObjectCount,
IWbemClassObject **apObjArray)
{
HRESULT hres = S_OK;
for (int i = 0; i < lObjectCount; i++)
{
printf("Event occurred\n");
}
return WBEM_S_NO_ERROR;
}
HRESULT EventSink::SetStatus(
/* [in] */ LONG lFlags,
/* [in] */ HRESULT hResult,
/* [in] */ BSTR strParam,
/* [in] */ IWbemClassObject __RPC_FAR *pObjParam
)
{
if(lFlags == WBEM_STATUS_COMPLETE)
{
printf("Call complete. hResult = 0x%X\n", hResult);
}
else if(lFlags == WBEM_STATUS_PROGRESS)
{
printf("Call in progress.\n");
}
return WBEM_S_NO_ERROR;
} // end of EventSink.cpp