Dela via


Åtkomst till prestandadata i C++

WMI API med höga prestanda är en serie gränssnitt som hämtar data från Prestandaräknarklasser. Dessa gränssnitt kräver användning av ett uppdateringsobjekt objekt för att öka samplingsfrekvensen. Mer information om hur du använder refresher-objektet i skript finns i Accessing Performance Data in Script och WMI Tasks: Performance Monitoring.

Följande avsnitt beskrivs i det här avsnittet:

Uppdatera prestandadata

Ett uppdateringsobjekt ökar dataproviderns och klientens prestanda genom att hämta data utan att korsa processgränser. Om både klienten och servern finns på samma dator, laddar en uppfräschare den högpresterande leverantören direkt i klientens process och kopierar data direkt från leverantörobjekt till klientobjekt. Om klienten och servern finns på olika datorer ökar uppdateringsprogrammet prestandan genom att cachelagra objekt på fjärrdatorn och överföra minimala datamängder till klienten.

En uppdatering:

  • Återansluter automatiskt en klient till en fjärr-WMI-tjänst när ett nätverksfel inträffar eller fjärrdatorn startas om.

    Som standard försöker en uppdatering att återansluta programmet till den relevanta högpresterande providern när en fjärranslutning mellan de två datorerna misslyckas. Om du vill förhindra återanslutningen skickar du flaggan WBEM_FLAG_REFRESH_NO_AUTO_RECONNECT i metodanropet Uppdatera. Skriptklienter måste ange egenskapen SWbemRefresher.AutoReconnect till FALSE.

  • Läser in flera objekt och uppräknare som tillhandahålls av samma eller olika leverantörer.

    Gör att du kan lägga till flera objekt, uppräknare eller båda i en uppdatering.

  • Räknar upp objekt.

    Precis som andra leverantörer kan en högpresterande provider räkna upp objekt.

När du har skrivit klart din klient med hög prestanda kan du vilja förbättra svarstiden. Eftersom gränssnittet IWbemObjectAccess är optimerat för hastighet är gränssnittet inte trådsäkert. Under en uppdateringsåtgärd får du därför inte åtkomst till det uppdateringsbara objektet eller uppräkningen. Om du vill skydda objekt mellan trådar under IWbemObjectAccess- metodanrop använder du metoderna IWbemObjectAccess::Lock och Unlock. Synkronisera trådarna så att du inte behöver låsa enskilda trådar för att få bättre prestanda. Att minska trådar och synkronisera grupper av objekt för uppdateringsåtgärder ger bästa övergripande prestanda.

Lägga till uppräknare i WMI-uppdateringsprogrammet

Både antalet instanser och data i varje instans uppdateras genom att lägga till en uppräknare i uppdateringsprogrammet så att varje anrop till IWbemRefresher::Uppdatera resulterar i en fullständig uppräkning.

Följande C++-kodexempel kräver följande referenser och #include-instruktioner för att kompilera korrekt.

#define _WIN32_DCOM

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

Följande procedur visar hur du lägger till en uppräknare i en uppdatering.

Om du vill lägga till en uppräknare i en uppdatering

  1. Anropa metoden IWbemConfigureRefresher::AddEnum med hjälp av sökvägen till det uppdateringsbara objektet och IWbemServices--gränssnittet.

    Uppdateringsverktyget returnerar en pekare till ett IWbemHiPerfEnum--gränssnitt. Du kan använda gränssnittet IWbemHiPerfEnum för att komma åt objekten i uppräkningen.

    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. Skapa en loop som utför följande åtgärder:

Exempel

I följande C++-kodexempel räknas en klass med höga prestanda upp, där klienten hämtar en egenskapsreferens från det första objektet och återanvänder referensen för resten av uppdateringsåtgärden. Varje anrop till metoden Uppdatera uppdaterar antalet instanser och instansdata.

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

prestandaräknarklasser

åtkomst till prestandadata i skript

Uppdatera WMI-data i skript

WMI-uppgifter: Prestandaövervakning

Övervakning av prestandadata

egenskapskvalificerare för formaterade prestandaräknareklasser

typer av WMI-prestandaräknare

Wmiadap.exe

QueryPerformanceCounter