Esempio: recupero di dati WMI dal computer locale in modo asincrono
È possibile utilizzare la procedura e gli esempi di codice in questo argomento per creare un'applicazione client WMI completa che esegue l'inizializzazione COM, connettersi a WMI nel computer locale, ottenere i dati in modo asincrono e quindi eseguire la pulizia. Questo esempio ottiene il nome del sistema operativo nel computer locale e lo visualizza.
Per eseguire l'applicazione WMI viene utilizzata la procedura seguente. I passaggi da 1 a 5 contengono tutti i passaggi necessari per configurare e connettersi a WMI e i passaggi 6 e sette in cui il nome del sistema operativo viene recuperato in modo asincrono.
Per ottenere i dati WMI dal computer locale in modo asincrono
Inizializzare i parametri COM con una chiamata a CoInitializeEx.
Per altre informazioni, vedere Inizializzazione di COM per un'applicazione WMI.
Inizializzare la sicurezza del processo COM chiamando CoInitializeSecurity.
Per altre informazioni, vedere Impostazione del livello di sicurezza del processo predefinito tramite C++.
Ottenere il localizzatore iniziale a WMI chiamando CoCreateInstance.
Per altre informazioni, vedere Creazione di una connessione a uno spazio dei nomi WMI.
Ottenere un puntatore a IWbemServices per lo spazio dei nomi root\cimv2 nel computer locale chiamando IWbemLocator::ConnectServer. Per altre informazioni su come connettersi a un computer remoto, vedere Esempio: Recupero di dati WMI da un computer remoto.
Per altre informazioni, vedere Creazione di una connessione a uno spazio dei nomi WMI.
Impostare la sicurezza proxy IWbemServices in modo che il servizio WMI possa rappresentare il client chiamando CoSetProxyBlanket.
Per altre informazioni, vedere Impostazione dei livelli di sicurezza in una connessione WMI.
Usare il puntatore IWbemServices per effettuare richieste a WMI. Questo esempio usa il metodo IWbemServices::ExecQueryAsync per ricevere i dati in modo asincrono. Ogni volta che si ricevono dati in modo asincrono, è necessario fornire un'implementazione di IWbemObjectSink. Questo esempio fornisce l'implementazione nella classe QuerySink. Il codice di implementazione e il codice del file di intestazione per questa classe vengono forniti seguendo l'esempio principale. Il metodo IWbemServices::ExecQueryAsync chiama il metodo QuerySink::Indicate ogni volta che vengono ricevuti i dati.
Per altre informazioni su come creare una richiesta WMI, vedere Modifica delle informazioni sulla classe e sull'istanza e chiamata di un metodo.
Attendere che i dati vengano recuperati in modo asincrono. Utilizzare il metodo IWbemServices::CancelAsyncCall per arrestare manualmente la chiamata asincrona.
L'esempio di codice seguente ottiene i dati WMI dal computer locale in modo asincrono.
#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.
}
Il file di intestazione seguente viene usato per la classe QuerySink. La classe QuerySink viene usata nell'esempio di codice precedente.
// 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
L'esempio di codice seguente è un'implementazione della classe QuerySink.
// 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