Accesso alle classi di prestazioni preinstallate WMI
Il repository WMI contiene classi di prestazioni preinstallate per tutti gli oggetti della libreria delle prestazioni. Ad esempio, le istanze della classe di prestazioni dei dati non elaborati Win32_PerfRawData_PerfProc_Process rappresentano i processi. Questo oggetto prestazioni è visibile in Monitoraggio di sistema come oggetto Process.
La proprietà PageFaultsPerSec di Win32_PerfRawData_PerfProc_Process rappresenta il contatore delle prestazioni dei Page Faults al secondo per il processo. Le classi Win32_PerfFormattedData contengono i valori dei dati calcolati visualizzati in Monitoraggio di sistema (Perfmon.exe). Il valore della proprietà PageFaultsPerSec di Win32_PerfFormattedData_PerfProc_Process corrisponde a quando viene visualizzato in Monitoraggio di sistema.
Usare l'API COM per WMI o l'API di scripting per WMI per accedere ai dati sulle prestazioni tramite le classi di contatori delle prestazioni . In entrambi i casi è necessario un oggetto di aggiornamento per ottenere ogni campione di dati. Per altre informazioni ed esempi di codice di script per l'uso di aggiornamenti e l'accesso alle classi di prestazioni, vedere attività WMI: Monitoraggio delle prestazioni. Per altre informazioni, vedere Accesso ai dati sulle prestazioni in Script.
Nell'esempio di codice C++ seguente viene usato il provider contatore delle prestazioni per accedere alle classi a prestazioni elevate predefinite. Crea un oggetto refresher e aggiunge un oggetto al refresher. L'oggetto è un'istanza di Win32_PerfRawData_PerfProc_Process che monitora le prestazioni di un processo specifico. Il codice legge solo una proprietà del contatore nell'oggetto processo, ovvero la proprietà VirtualBytes. Il codice richiede che i riferimenti e le istruzioni #include seguenti vengano compilati correttamente.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
La procedura seguente illustra come accedere ai dati da un provider ad alte prestazioni in C++.
Per accedere ai dati da un provider ad alte prestazioni in C++
Stabilire una connessione allo spazio dei nomi WMI e impostare la sicurezza WMI usando una chiamata a IWbemLocator::ConnectServer e CoSetProxyBlanket.
Questo passaggio è un passaggio standard per la creazione di qualsiasi applicazione client WMI. Per altre informazioni, vedere Creazione di un'applicazione WMI tramite C++.
Creare un oggetto refresher usando CoCreateInstance con CLSID_WbemRefresher. Richiedi un'interfaccia IWbemConfigureRefresher tramite il metodo QueryInterface. Richiedere un'interfaccia IWbemRefresher tramite il metodo QueryInterface.
L'interfaccia IWbemRefresher è l'interfaccia principale dell'oggetto WMI Refresher.
Nell'esempio di codice C++ seguente viene illustrato come recuperare IWbemConfigureRefresher.
IWbemRefresher* pRefresher = NULL; HRESULT hr = CoCreateInstance( CLSID_WbemRefresher, NULL, CLSCTX_INPROC_SERVER, IID_IWbemRefresher, (void**) &pRefresher); IWbemConfigureRefresher* pConfig = NULL; pRefresher->QueryInterface( IID_IWbemConfigureRefresher, (void**) &pConfig );
Aggiungere un oggetto al metodo refresher tramite una chiamata al metodo IWbemConfigureRefresher::AddObjectByPath.
Quando si aggiunge un oggetto all'aggiornamento, WMI aggiorna l'oggetto ogni volta che si chiama il metodo IWbemRefresher::Refresh. L'oggetto che aggiungi designa il provider nei suoi qualificatori di classe.
Nell'esempio di codice C++ seguente viene illustrato come chiamare AddObjectByPath.
IWbemClassObject* pObj = NULL; IWbemServices* pNameSpace = NULL; // Add the instance to be refreshed. hr = pConfig->AddObjectByPath( pNameSpace, L"Win32_PerfRawData_PerfProc_Process.Name=\"WINWORD\"", 0L, NULL, &pObj, NULL ); if (FAILED(hr)) { cout << "Could not add object. Error code: 0x" << hex << hr << endl; pNameSpace->Release(); return hr; }
Per configurare un accesso più rapido all'oggetto, connettersi all'interfaccia IWbemObjectAccess tramite QueryInterface nell'interfaccia IWbemClassObject.
Nell'esempio di codice C++ seguente viene illustrato come recuperare un puntatore all'oggetto usando IWbemObjectAccess anziché IWbemClassObject.
// For quick property retrieval, use IWbemObjectAccess. IWbemObjectAccess* pAcc = NULL; pObj->QueryInterface( IID_IWbemObjectAccess, (void**) &pAcc ); // This is not required. pObj->Release();
L'interfaccia IWbemObjectAccess aumenta le prestazioni perché è possibile ottenere handle per proprietà contatore specifiche ed è necessario bloccare e sbloccare l'oggetto nel codice, un'operazione che viene eseguita da IWbemClassObject per ogni accesso alle proprietà.
Ottieni gli handle delle proprietà da esaminare tramite chiamate al metodo IWbemObjectAccess::GetPropertyHandle.
Gli handle di proprietà sono gli stessi per tutte le istanze di una classe, il che significa che è possibile utilizzare l'handle di proprietà recuperato da una specifica istanza per tutte le istanze di quella classe. È anche possibile ottenere un handle da un oggetto di classe per recuperare i valori delle proprietà da un oggetto di istanza.
Nell'esempio di codice C++ seguente viene illustrato come recuperare un handle di proprietà.
// Get a property handle for the VirtualBytes property long lVirtualBytesHandle = 0; DWORD dwVirtualBytes = 0; CIMTYPE variant; hr = pAcc->GetPropertyHandle(L"VirtualBytes", &variant, &lVirtualBytesHandle ); if (FAILED(hr)) { cout << "Could not get property handle. Error code: 0x" << hex << hr << endl; return hr; }
Creare un ciclo di programmazione che esegue le azioni seguenti:
Aggiornare l'oggetto con una chiamata a IWbemRefresher::Refresh usando il puntatore creato nella chiamata precedente a CoCreateInstance.
In questa chiamata, l'aggiornamento WMI aggiorna l'oggetto client usando i dati forniti dal provider.
Eseguire qualsiasi azione in base alle esigenze sull'oggetto, ad esempio il recupero di un nome di proprietà, un tipo di dati o un valore.
È possibile accedere alla proprietà tramite l'handle di proprietà ottenuto in precedenza. A causa della chiamata Refresh, WMI aggiorna ogni volta la proprietà tramite il ciclo.
L'esempio C++ seguente illustra come usare l'API WMI ad alte prestazioni.
// Get the local locator object
IWbemServices* pNameSpace = NULL;
IWbemLocator* pWbemLocator = NULL;
CIMTYPE variant;
VARIANT VT;
CoCreateInstance( CLSID_WbemLocator, NULL,
CLSCTX_INPROC_SERVER, IID_IWbemLocator, (void**) &pWbemLocator
);
// Connect to the desired namespace
BSTR bstrNameSpace = SysAllocString( L"\\\\.\\root\\cimv2" );
HRESULT hr = WBEM_S_NO_ERROR;
hr = pWbemLocator->ConnectServer(
bstrNameSpace, // Namespace name
NULL, // User name
NULL, // Password
NULL, // Locale
0L, // Security flags
NULL, // Authority
NULL, // Wbem context
&pNameSpace // Namespace
);
if ( SUCCEEDED( hr ) )
{
// Set namespace security.
IUnknown* pUnk = NULL;
pNameSpace->QueryInterface( IID_IUnknown, (void**) &pUnk );
hr = CoSetProxyBlanket(
pNameSpace,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hr))
{
cout << "Cannot set proxy blanket. Error code: 0x"
<< hex << hr << endl;
pNameSpace->Release();
return hr;
}
hr = CoSetProxyBlanket(pUnk,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hr))
{
cout << "Cannot set proxy blanket. Error code: 0x"
<< hex << hr << endl;
pUnk->Release();
return hr;
}
// Clean up the IUnknown.
pUnk->Release();
IWbemRefresher* pRefresher = NULL;
IWbemConfigureRefresher* pConfig = NULL;
// Create a WMI Refresher and get a pointer to the
// IWbemConfigureRefresher interface.
CoCreateInstance(CLSID_WbemRefresher,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemRefresher,
(void**) &pRefresher
);
pRefresher->QueryInterface(IID_IWbemConfigureRefresher,
(void**) &pConfig );
IWbemClassObject* pObj = NULL;
// Add the instance to be refreshed.
pConfig->AddObjectByPath(
pNameSpace,
L"Win32_PerfRawData_PerfProc_Process.Name=\"WINWORD\"",
0L,
NULL,
&pObj,
NULL
);
if (FAILED(hr))
{
cout << "Cannot add object. Error code: 0x"
<< hex << hr << endl;
pNameSpace->Release();
return hr;
}
// For quick property retrieval, use IWbemObjectAccess.
IWbemObjectAccess* pAcc = NULL;
pObj->QueryInterface(IID_IWbemObjectAccess,
(void**) &pAcc );
// This is not required.
pObj->Release();
// Get a property handle for the VirtualBytes property.
long lVirtualBytesHandle = 0;
DWORD dwVirtualBytes = 0;
pAcc->GetPropertyHandle(L"VirtualBytes",
&variant,
&lVirtualBytesHandle );
// Refresh the object ten times and retrieve the value.
for( int x = 0; x < 10; x++ )
{
pRefresher->Refresh( 0L );
pAcc->ReadDWORD( lVirtualBytesHandle, &dwVirtualBytes );
printf( "Process is using %lu bytes\n", dwVirtualBytes );
// Sleep for a second.
Sleep( 1000 );
}
// Clean up all the objects.
pAcc->Release();
// Done with these too.
pConfig->Release();
pRefresher->Release();
pNameSpace->Release();
}
SysFreeString( bstrNameSpace );
pWbemLocator->Release();