Voorbeeld: Gebeurtenismeldingen ontvangen via WMI
U kunt de procedure en codevoorbeeld in dit onderwerp gebruiken om de WMI-clienttoepassing te voltooien die COM-initialisatie uitvoert, verbinding maakt met WMI op de lokale computer, een gebeurtenismelding ontvangt en vervolgens opschoont. In het voorbeeld wordt de gebruiker van een gebeurtenis op de hoogte gebracht wanneer er een nieuw proces wordt gemaakt. De gebeurtenissen worden asynchroon ontvangen.
De volgende procedure wordt gebruikt om de WMI-toepassing uit te voeren. Stap 1 tot en met 5 bevat alle stappen die nodig zijn om WMI in te stellen en er verbinding mee te maken, en stap 6 is waar de gebeurtenismeldingen worden ontvangen.
Een gebeurtenismelding ontvangen via WMI-
Initialiseer COM-parameters met een aanroep naar CoInitializeEx.
Zie COM initialiseren voor een WMI-toepassingvoor meer informatie.
Initialiseer com-procesbeveiliging door CoInitializeSecurityaan te roepen.
Zie Het standaardniveau voor procesbeveiliging instellen met C++voor meer informatie.
Haal de eerste locator naar WMI op door CoCreateInstance-aan te roepen.
Zie Een verbinding maken met een WMI-naamruimtevoor meer informatie.
Vraag een aanwijzer naar IWbemServices- voor de root\cimv2-naamruimte op de lokale computer door IWbemLocator::ConnectServeraan te roepen. Zie voorbeeld: WMI-gegevens ophalen van een externe computerom verbinding te maken met een externe computer.
Zie Een verbinding maken met een WMI-naamruimtevoor meer informatie.
Stel IWbemServices proxybeveiliging in, zodat de WMI-service de client kan imiteren door CoSetProxyBlanket-aan te roepen.
Zie Beveiligingsniveaus instellen voor een WMI-verbindingvoor meer informatie.
Gebruik de aanwijzer IWbemServices om aanvragen naar WMI te verzenden. In dit voorbeeld wordt de methode IWbemServices::ExecNotificationQueryAsync methode gebruikt om asynchrone gebeurtenissen te ontvangen. Wanneer u asynchrone gebeurtenissen ontvangt, moet u een implementatie van IWbemObjectSinkopgeven. Dit voorbeeld bevat de implementatie in de klasse EventSink. De implementatiecode en headerbestandscode voor deze klasse worden weergegeven onder het hoofdvoorbeeld. De methode IWbemServices::ExecNotificationQueryAsync roept de methode EventSink::Geef methode aan wanneer een gebeurtenis wordt ontvangen. In dit voorbeeld wordt de methode EventSink::Geef methode aan wanneer een proces wordt gemaakt. Als u dit voorbeeld wilt testen, voert u de code uit en start u een proces zoals Notepad.exe. Hiermee wordt een gebeurtenismelding geactiveerd.
Zie Manipulating Class and Instance Information and Calling a Methodvoor meer informatie over het indienen van aanvragen van WMI.
De volgende voorbeeldcode ontvangt gebeurtenismeldingen via 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.
}
Het volgende headerbestand wordt gebruikt voor de klasse EventSink. De EventSink-klasse wordt gebruikt in het vorige codevoorbeeld.
// 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
De volgende voorbeeldcode is een implementatie van de klasse EventSink.
// 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