Beispiel: Asynchrones Abrufen von WMI-Daten vom lokalen Computer
Sie können die Verfahren und Codebeispiele in diesem Thema verwenden, um eine vollständige WMI-Clientanwendung zu erstellen, die COM-Initialisierung durchführt, eine Verbindung mit WMI auf dem lokalen Computer herstellt, Daten asynchron abruft und anschließend bereinigt. In diesem Beispiel wird der Name des Betriebssystems auf dem lokalen Computer angezeigt und angezeigt.
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 die Schritte 6 und sieben enthalten, in denen der Name des Betriebssystems asynchron abgerufen wird.
So rufen Sie WMI-Daten asynchron vom lokalen Computer
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. Weitere 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::ExecQueryAsync Methode verwendet, um die Daten asynchron zu empfangen. Immer wenn Sie Daten asynchron empfangen, müssen Sie eine Implementierung von IWbemObjectSinkbereitstellen. In diesem Beispiel wird die Implementierung in der QuerySink-Klasse bereitgestellt. Der Implementierungscode und der Headerdateicode für diese Klasse werden im Anschluss an das Hauptbeispiel bereitgestellt. Die IWbemServices::ExecQueryAsync--Methode ruft die QuerySink::Indicate-Methode auf, wenn die Daten empfangen werden.
Weitere Informationen zum Erstellen einer WMI-Anforderung finden Sie unter Bearbeiten von Klassen- und Instanzinformationen und Aufrufen einer Methode.
Warten Sie, bis die Daten asynchron abgerufen werden. Verwenden Sie die IWbemServices::CancelAsyncCall Methode, um den asynchronen Aufruf manuell zu beenden.
Im folgenden Codebeispiel werden WMI-Daten asynchron vom lokalen Computer abgerufen.
#include "querysink.h"
int main(int argc, 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 authentication
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: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system.
// The IWbemService::ExecQueryAsync method will call
// the QuerySink::Indicate method when it receives a result
// and the QuerySink::Indicate method will display the OS name
QuerySink* pResponseSink = new QuerySink();
pResponseSink->AddRef();
hres = pSvc->ExecQueryAsync(bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_OperatingSystem"),
WBEM_FLAG_BIDIRECTIONAL,
NULL,
pResponseSink);
if (FAILED(hres))
{
cout << "Query for operating system name failed."
<< " Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
pResponseSink->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 7: -------------------------------------------------
// Wait to get the data from the query in step 6 -----------
Sleep(500);
pSvc->CancelAsyncCall(pResponseSink);
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 0; // Program successfully completed.
}
Die folgende Headerdatei wird für die QuerySink-Klasse verwendet. Die QuerySink-Klasse wird im vorherigen Codebeispiel verwendet.
// QuerySink.h
#ifndef QUERYSINK_H
#define QUERYSINK_H
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
class QuerySink : public IWbemObjectSink
{
LONG m_lRef;
bool bDone;
CRITICAL_SECTION threadLock; // for thread safety
public:
QuerySink() { m_lRef = 0; bDone = false;
InitializeCriticalSection(&threadLock); }
~QuerySink() { bDone = true;
DeleteCriticalSection(&threadLock); }
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
);
bool IsDone();
};
#endif // end of QuerySink.h
Das folgende Codebeispiel ist eine Implementierung der QuerySink-Klasse.
// QuerySink.cpp
#include "querysink.h"
ULONG QuerySink::AddRef()
{
return InterlockedIncrement(&m_lRef);
}
ULONG QuerySink::Release()
{
LONG lRef = InterlockedDecrement(&m_lRef);
if(lRef == 0)
delete this;
return lRef;
}
HRESULT QuerySink::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 QuerySink::Indicate(long lObjectCount,
IWbemClassObject **apObjArray)
{
HRESULT hres = S_OK;
for (int i = 0; i < lObjectCount; i++)
{
VARIANT varName;
hres = apObjArray[i]->Get(_bstr_t(L"Name"),
0, &varName, 0, 0);
if (FAILED(hres))
{
cout << "Failed to get the data from the query"
<< " Error code = 0x"
<< hex << hres << endl;
return WBEM_E_FAILED; // Program has failed.
}
printf("Name: %ls\n", V_BSTR(&varName));
}
return WBEM_S_NO_ERROR;
}
HRESULT QuerySink::SetStatus(
/* [in] */ LONG lFlags,
/* [in] */ HRESULT hResult,
/* [in] */ BSTR strParam,
/* [in] */ IWbemClassObject __RPC_FAR *pObjParam
)
{
if(lFlags == WBEM_STATUS_COMPLETE)
{
printf("Call complete.\n");
EnterCriticalSection(&threadLock);
bDone = true;
LeaveCriticalSection(&threadLock);
}
else if(lFlags == WBEM_STATUS_PROGRESS)
{
printf("Call in progress.\n");
}
return WBEM_S_NO_ERROR;
}
bool QuerySink::IsDone()
{
bool done = true;
EnterCriticalSection(&threadLock);
done = bDone;
LeaveCriticalSection(&threadLock);
return done;
} // end of QuerySink.cpp