Delen via


Toegang tot prestatiegegevens in C++

De WMI high-performance API is een reeks interfaces die gegevens ophalen uit prestatiemeteritemsklassen. Voor deze interfaces moet een vernieuwingsfunctie object worden gebruikt om de steekproefsnelheid te verhogen. Zie Accessing Performance Data in Script en WMI-taken: Prestatiemonitoringvoor meer informatie over het gebruik van het updateobject in een script.

In dit onderwerp worden de volgende secties besproken:

Prestatiegegevens vernieuwen

Een vernieuwingsobject verhoogt de prestaties van de gegevensprovider en de client door gegevens op te halen zonder procesgrenzen te overschrijden. Als de client en de server zich op dezelfde computer bevinden, laadt een vernieuwer de hoogwaardige provider intern naar de client en kopieert gegevens rechtstreeks van providerobjecten naar clientobjecten. Als de client en de server zich op verschillende computers bevinden, verhoogt de vernieuwing de prestaties door objecten op de externe computer in de cache op te slaan en minimale gegevenssets naar de client te verzenden.

Een opfrisser ook:

  • Hiermee wordt een client automatisch opnieuw verbonden met een externe WMI-service wanneer er een netwerkfout optreedt of wordt de externe computer opnieuw opgestart.

    Standaard probeert een vernieuwingsfunctie uw toepassing opnieuw te verbinden met de relevante provider met hoge prestaties wanneer een externe verbinding tussen de twee computers mislukt. Als u wilt voorkomen dat er opnieuw verbinding wordt gemaakt, geeft u de vlag WBEM_FLAG_REFRESH_NO_AUTO_RECONNECT door in de methode-aanroep vernieuwen. Scriptclients moeten de eigenschap SWbemRefresher.AutoReconnect instellen op FALSE-.

  • Laadt meerdere objecten en opsommingen die worden geleverd door dezelfde of verschillende providers.

    Hiermee kunt u meerdere objecten, opsommingen of beide toevoegen aan een ververser.

  • Inventariseert objecten.

    Net als andere providers kan een provider met hoge prestaties objecten inventariseren.

Nadat u klaar bent met het schrijven van uw krachtige client, kunt u de reactietijd verbeteren. Omdat de IWbemObjectAccess interface is geoptimaliseerd voor snelheid, is de interface niet intrinsiek threadsafe. Daarom hebt u tijdens een vernieuwingsbewerking geen toegang tot het vernieuwbare object of de opsomming. Als u objecten tussen threads wilt beveiligen tijdens methodeoproepen van IWbemObjectAccess, gebruikt u de methode IWbemObjectAccess::Lock en Unlock methoden. Voor betere prestaties synchroniseert u uw threads, zodat u afzonderlijke threads niet hoeft te vergrendelen. Het verminderen van threads en het synchroniseren van groepen objecten voor vernieuwingsbewerkingen biedt de beste algehele prestaties.

Enumerators toevoegen aan WMI Refresher

Zowel het aantal exemplaren als de gegevens in elke instantie wordt vernieuwd door een opsomming toe te voegen aan de vernieuwingsfunctie, zodat elke aanroep naar IWbemRefresher::Refresh resulteert in een volledige opsomming.

Voor het volgende C++-codevoorbeeld zijn de volgende verwijzingen en #include instructies vereist om correct te compileren.

#define _WIN32_DCOM

#include <iostream>
using namespace std;
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")

In de volgende procedure wordt getoond hoe u een enumerator toevoegt aan een ververser.

Een enumerator toevoegen aan een refresher

  1. Roep de methode IWbemConfigureRefresher::AddEnum- aan met behulp van het pad naar het vernieuwbare object en de interface IWbemServices.

    De vernieuwer retourneert een pointer naar een IWbemHiPerfEnum interface. U kunt de IWbemHiPerfEnum-interface gebruiken om toegang te krijgen tot de objecten in de opsomming.

    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;
    
  2. Maak een lus waarmee de volgende acties worden uitgevoerd:

Voorbeeld

In het volgende C++-codevoorbeeld wordt een klasse met hoge prestaties opgesomd, waarbij de client een eigenschapsgreep ophaalt uit het eerste object en de ingang opnieuw gebruikt voor de rest van de vernieuwingsbewerking. Elke aanroep naar de methode Refresh werkt het aantal exemplaren en de instantiegegevens bij.

#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;
}

Prestatiemeterklassen

toegang tot prestatiegegevens in script

WMI-gegevens vernieuwen in scripts

WMI-taken: Prestatiebewaking

Prestatiegegevens bewaken

Eigenschappenkwalificaties voor opgemaakte prestatiemeterklassen

WMI-prestatiemeter types

Wmiadap.exe

QueryPerformanceCounter