Accesso ai dati sulle prestazioni in C++
L'API WMI ad alte prestazioni è una serie di interfacce che ottengono dati da classi di contatori delle prestazioni. Queste interfacce richiedono l'uso di un oggetto aggiornatore per aumentare la frequenza di campionamento. Per altre informazioni sull'uso dell'oggetto refresher nello scripting, vedere Accesso ai dati sulle prestazioni nelle attività script e WMI: Monitoraggio delle prestazioni.
Le sezioni seguenti sono illustrate in questo argomento:
- Aggiornamento dei dati sulle prestazioni
- Aggiunta di enumeratori al aggiornatore WMI
- Esempio
- Argomenti correlati
Aggiornamento dei dati sulle prestazioni
Un oggetto refresher aumenta le prestazioni del provider di dati e del client recuperando i dati senza superare i limiti del processo. Se sia il client che il server si trovano nello stesso computer, un aggiornamento carica il provider ad alte prestazioni nel client e copia i dati direttamente dagli oggetti provider negli oggetti client. Se il client e il server si trovano in computer diversi, l'aggiornamento aumenta le prestazioni memorizzando nella cache gli oggetti nel computer remoto e trasmettendo set di dati minimi al client.
Un aggiornamento anche:
Riconnette automaticamente un client a un servizio WMI remoto quando si verifica un errore di rete o il computer remoto viene riavviato.
Per impostazione predefinita, un aggiornamento tenta di riconnettere l'applicazione al provider ad alte prestazioni pertinente quando una connessione remota tra i due computer ha esito negativo. Per impedire la riconnessione, passare il flag WBEM_FLAG_REFRESH_NO_AUTO_RECONNECT nella chiamata al metodo Refresh . I client di scripting devono impostare la proprietà SWbemRefresher.AutoReconnect su FALSE.
Carica più oggetti e enumeratori forniti dagli stessi provider o diversi.
Consente di aggiungere più oggetti, enumeratori o entrambi a un aggiornamento.
Enumera oggetti.
Come altri provider, un provider ad alte prestazioni può enumerare oggetti.
Al termine della scrittura del client ad alte prestazioni, è possibile migliorare il tempo di risposta. Poiché l'interfaccia IWbemObjectAccess è ottimizzata per la velocità, l'interfaccia non è intrinsecamente threadsafe. Pertanto, durante un'operazione di aggiornamento, non accedere all'oggetto aggiornabile o all'enumerazione. Per proteggere gli oggetti tra thread durante le chiamate al metodo IWbemObjectAccess, usare i metodi IWbemObjectAccess::Lock e Unlock. Per migliorare le prestazioni, sincronizzare i thread in modo che non sia necessario bloccare singoli thread. La riduzione dei thread e la sincronizzazione di gruppi di oggetti per le operazioni di aggiornamento offrono le migliori prestazioni complessive.
Aggiunta di enumeratori al aggiornatore WMI
Sia il numero di istanze che i dati in ogni istanza vengono aggiornati aggiungendo un enumeratore al aggiornatore in modo che ogni chiamata a IWbemRefresher::Refresh risultati in un'enumerazione completa.
Nell'esempio di codice C++ seguente sono necessari i riferimenti seguenti e le istruzioni #include per la compilazione corretta.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
La procedura seguente illustra come aggiungere un enumeratore a un aggiornamento.
Per aggiungere un enumeratore a un aggiornamento
Chiamare il metodo IWbemConfigureRefresher::AddEnum usando il percorso dell'oggetto aggiornabile e l'interfaccia IWbemServices .
L'aggiornamento restituisce un puntatore a un'interfaccia IWbemHiPerfEnum . È possibile usare l'interfaccia IWbemHiPerfEnum per accedere agli oggetti nell'enumerazione.
IWbemHiPerfEnum* pEnum = NULL; long lID; IWbemConfigureRefresher* pConfig; IWbemServices* pNameSpace; // Add an enumerator to the refresher. if (FAILED (hr = pConfig->AddEnum( pNameSpace, L"Win32_PerfRawData_PerfProc_Process", 0, NULL, &pEnum, &lID))) { goto CLEANUP; } pConfig->Release(); pConfig = NULL;
Creare un ciclo che esegue le azioni seguenti:
Aggiorna l'oggetto usando una chiamata a IWbemRefresher::Refresh.
Fornisce una matrice di puntatori dell'interfaccia IWbemObjectAccess al metodo IWbemHiPerfEnum::GetObjects .
Accede alle proprietà dell'enumeratore usando i metodi IWbemObjectAccess passati a GetObjects.
Un handle di proprietà può essere passato a ogni istanza di IWbemObjectAccess per recuperare il valore aggiornato. Il client deve chiamare Release per rilasciare i puntatori IWbemObjectAccessrestituiti da GetObjects.
Esempio
L'esempio di codice C++ seguente enumera una classe ad alte prestazioni, in cui il client recupera un handle di proprietà dal primo oggetto e riutilizza l'handle per il resto dell'operazione di aggiornamento. Ogni chiamata al metodo Refresh aggiorna il numero di istanze e i dati dell'istanza.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
int __cdecl wmain(int argc, wchar_t* argv[])
{
// To add error checking,
// check returned HRESULT below where collected.
HRESULT hr = S_OK;
IWbemRefresher *pRefresher = NULL;
IWbemConfigureRefresher *pConfig = NULL;
IWbemHiPerfEnum *pEnum = NULL;
IWbemServices *pNameSpace = NULL;
IWbemLocator *pWbemLocator = NULL;
IWbemObjectAccess **apEnumAccess = NULL;
BSTR bstrNameSpace = NULL;
long lID = 0;
long lVirtualBytesHandle = 0;
long lIDProcessHandle = 0;
DWORD dwVirtualBytes = 0;
DWORD dwProcessId = 0;
DWORD dwNumObjects = 0;
DWORD dwNumReturned = 0;
DWORD dwIDProcess = 0;
DWORD i=0;
int x=0;
if (FAILED (hr = CoInitializeEx(NULL,COINIT_MULTITHREADED)))
{
goto CLEANUP;
}
if (FAILED (hr = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_NONE,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, 0)))
{
goto CLEANUP;
}
if (FAILED (hr = CoCreateInstance(
CLSID_WbemLocator,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(void**) &pWbemLocator)))
{
goto CLEANUP;
}
// Connect to the desired namespace.
bstrNameSpace = SysAllocString(L"\\\\.\\root\\cimv2");
if (NULL == bstrNameSpace)
{
hr = E_OUTOFMEMORY;
goto CLEANUP;
}
if (FAILED (hr = pWbemLocator->ConnectServer(
bstrNameSpace,
NULL, // User name
NULL, // Password
NULL, // Locale
0L, // Security flags
NULL, // Authority
NULL, // Wbem context
&pNameSpace)))
{
goto CLEANUP;
}
pWbemLocator->Release();
pWbemLocator=NULL;
SysFreeString(bstrNameSpace);
bstrNameSpace = NULL;
if (FAILED (hr = CoCreateInstance(
CLSID_WbemRefresher,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemRefresher,
(void**) &pRefresher)))
{
goto CLEANUP;
}
if (FAILED (hr = pRefresher->QueryInterface(
IID_IWbemConfigureRefresher,
(void **)&pConfig)))
{
goto CLEANUP;
}
// Add an enumerator to the refresher.
if (FAILED (hr = pConfig->AddEnum(
pNameSpace,
L"Win32_PerfRawData_PerfProc_Process",
0,
NULL,
&pEnum,
&lID)))
{
goto CLEANUP;
}
pConfig->Release();
pConfig = NULL;
// Get a property handle for the VirtualBytes property.
// Refresh the object ten times and retrieve the value.
for(x = 0; x < 10; x++)
{
dwNumReturned = 0;
dwIDProcess = 0;
dwNumObjects = 0;
if (FAILED (hr =pRefresher->Refresh(0L)))
{
goto CLEANUP;
}
hr = pEnum->GetObjects(0L,
dwNumObjects,
apEnumAccess,
&dwNumReturned);
// If the buffer was not big enough,
// allocate a bigger buffer and retry.
if (hr == WBEM_E_BUFFER_TOO_SMALL
&& dwNumReturned > dwNumObjects)
{
apEnumAccess = new IWbemObjectAccess*[dwNumReturned];
if (NULL == apEnumAccess)
{
hr = E_OUTOFMEMORY;
goto CLEANUP;
}
SecureZeroMemory(apEnumAccess,
dwNumReturned*sizeof(IWbemObjectAccess*));
dwNumObjects = dwNumReturned;
if (FAILED (hr = pEnum->GetObjects(0L,
dwNumObjects,
apEnumAccess,
&dwNumReturned)))
{
goto CLEANUP;
}
}
else
{
if (hr == WBEM_S_NO_ERROR)
{
hr = WBEM_E_NOT_FOUND;
goto CLEANUP;
}
}
// First time through, get the handles.
if (0 == x)
{
CIMTYPE VirtualBytesType;
CIMTYPE ProcessHandleType;
if (FAILED (hr = apEnumAccess[0]->GetPropertyHandle(
L"VirtualBytes",
&VirtualBytesType,
&lVirtualBytesHandle)))
{
goto CLEANUP;
}
if (FAILED (hr = apEnumAccess[0]->GetPropertyHandle(
L"IDProcess",
&ProcessHandleType,
&lIDProcessHandle)))
{
goto CLEANUP;
}
}
for (i = 0; i < dwNumReturned; i++)
{
if (FAILED (hr = apEnumAccess[i]->ReadDWORD(
lVirtualBytesHandle,
&dwVirtualBytes)))
{
goto CLEANUP;
}
if (FAILED (hr = apEnumAccess[i]->ReadDWORD(
lIDProcessHandle,
&dwIDProcess)))
{
goto CLEANUP;
}
wprintf(L"Process ID %lu is using %lu bytes\n",
dwIDProcess, dwVirtualBytes);
// Done with the object
apEnumAccess[i]->Release();
apEnumAccess[i] = NULL;
}
if (NULL != apEnumAccess)
{
delete [] apEnumAccess;
apEnumAccess = NULL;
}
// Sleep for a second.
Sleep(1000);
}
// exit loop here
CLEANUP:
if (NULL != bstrNameSpace)
{
SysFreeString(bstrNameSpace);
}
if (NULL != apEnumAccess)
{
for (i = 0; i < dwNumReturned; i++)
{
if (apEnumAccess[i] != NULL)
{
apEnumAccess[i]->Release();
apEnumAccess[i] = NULL;
}
}
delete [] apEnumAccess;
}
if (NULL != pWbemLocator)
{
pWbemLocator->Release();
}
if (NULL != pNameSpace)
{
pNameSpace->Release();
}
if (NULL != pEnum)
{
pEnum->Release();
}
if (NULL != pConfig)
{
pConfig->Release();
}
if (NULL != pRefresher)
{
pRefresher->Release();
}
CoUninitialize();
if (FAILED (hr))
{
wprintf (L"Error status=%08x\n",hr);
}
return 1;
}
Argomenti correlati