Accesso alle classi di prestazioni preinstallate di 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 elaborate 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 page al secondo per il processo. Le classi Win32_PerfFormattedData contengono i valori di dati calcolati visualizzati in Monitoraggio sistema (Perfmon.exe). Il valore della proprietà PageFaultsPerSec di Win32_PerfFormattedData_PerfProc_Process è uguale a quando viene visualizzato in Monitoraggio sistema.

Usare l'API COM per WMI o l'API scripting per WMI per accedere ai dati sulle prestazioni tramite le classi contatori delle prestazioni. In entrambi i casi è necessario un oggetto aggiornatore per ottenere ogni esempio di dati. Per altre informazioni ed esempi di codice 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 nello script.

Accesso ai dati sulle prestazioni da C++

Nell'esempio di codice C++ seguente viene usato il provider contatore prestazioni per accedere alle classi ad alte prestazioni predefinite. Crea un oggetto refresher e aggiunge un oggetto al aggiornatore. L'oggetto è un'istanza di Win32_PerfRawData_PerfProc_Process che monitora le prestazioni di un processo specifico. Il codice legge solo una proprietà contatore nell'oggetto process, la proprietà VirtualBytes . Il codice richiede i riferimenti e le istruzioni di #include seguenti 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 accedere ai dati da un provider ad alte prestazioni in C++.

Per accedere ai dati da un provider ad alte prestazioni in C++

  1. 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++.

  2. Creare un oggetto refresher usando CoCreateInstance con CLSID_WbemRefresher. Richiedere un'interfaccia IWbemConfigureRefresher tramite il metodo QueryInterface . Richiedere un'interfaccia IWbemRefresher tramite il metodo QueryInterface .

    L'interfaccia IWbemRefresher è l'interfaccia principale per l'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
      );
    
  3. Aggiungere un oggetto al aggiornatore 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 aggiunto designa il provider nei relativi 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;
    }
    
  4. Per configurare l'accesso più veloce 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à del contatore specifiche e richiede di bloccare e sbloccare l'oggetto nel codice, ovvero un'operazione eseguita da IWbemClassObject per ogni accesso alle proprietà.

  5. Ottenere gli handle delle proprietà da esaminare usando le chiamate al metodo IWbemObjectAccess::GetPropertyHandle .

    Gli handle delle proprietà sono uguali per tutte le istanze di una classe, che significa che usare l'handle di proprietà recuperato da un'istanza specifica per tutte le istanze di una classe specifica. È anche possibile ottenere un handle da un oggetto classe per recuperare i valori delle proprietà da un oggetto 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;
        }
    
  6. 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 dell'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 Aggiorna , WMI aggiorna la proprietà ogni volta che si attraversa il ciclo.

Nell'esempio C++ seguente viene illustrato 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();

Classi di contatori delle prestazioni

Attività WMI: Monitoraggio delle prestazioni