Mengakses Data Performa di C++

API berkinerja tinggi WMI adalah serangkaian antarmuka yang mendapatkan data dari Kelas Penghitung Kinerja. Antarmuka ini memerlukan penggunaan objek penyegaran untuk meningkatkan laju pengambilan sampel. Untuk informasi selengkapnya tentang menggunakan objek penyegaran dalam pembuatan skrip, lihat Mengakses Data Performa di Tugas Skrip dan WMI: Pemantauan Performa.

Bagian berikut dibahas dalam topik ini:

Menyegarkan Data Performa

Objek penyegar meningkatkan penyedia data dan performa klien dengan mengambil data tanpa melewati batas proses. Jika klien dan server terletak di komputer yang sama, penyegaran memuat penyedia berkinerja tinggi dalam proses ke klien, dan menyalin data langsung dari objek penyedia ke objek klien. Jika klien dan server terletak di komputer yang berbeda, penyegaran meningkatkan performa dengan penembolokan objek di komputer jarak jauh, dan mengirimkan himpunan data minimal ke klien.

Penyegaran juga:

  • Secara otomatis menyambungkan kembali klien ke layanan WMI jarak jauh ketika terjadi kesalahan jaringan, atau komputer jarak jauh dimulai ulang.

    Secara default, penyegaran mencoba menyambungkan kembali aplikasi Anda ke penyedia berkinerja tinggi yang relevan ketika koneksi jarak jauh antara kedua komputer gagal. Untuk mencegah koneksi ulang, berikan bendera WBEM_FLAG_REFRESH_NO_AUTO_RECONNECT dalam panggilan metode Refresh . Klien pembuatan skrip harus mengatur properti SWbemRefresher.AutoReconnect ke FALSE.

  • Memuat beberapa objek dan enumerator yang disediakan oleh penyedia yang sama atau berbeda.

    Memungkinkan Anda menambahkan beberapa objek, enumerator, atau keduanya ke penyegaran.

  • Menghitung objek.

    Seperti penyedia lain, penyedia berkinerja tinggi dapat menghitung objek.

Setelah selesai menulis klien berkinerja tinggi, Anda mungkin ingin meningkatkan waktu respons Anda. Karena antarmuka IWbemObjectAccess dioptimalkan untuk kecepatan, antarmuka tidak secara intrinsik threadsafe. Oleh karena itu, selama operasi refresh, jangan akses objek atau enumerasi yang dapat di-refresh. Untuk melindungi objek di seluruh utas selama panggilan metode IWbemObjectAccess , gunakan metode IWbemObjectAccess::Lock dan Unlock . Untuk meningkatkan performa, sinkronkan utas Anda sehingga Anda tidak perlu mengunci utas individual. Mengurangi utas dan menyinkronkan grup objek untuk operasi refresh memberikan performa keseluruhan terbaik.

Menambahkan Enumerator ke Penyegar WMI

Jumlah instans dan data di setiap instans di-refresh dengan menambahkan enumerator ke penyegaran sehingga setiap panggilan ke IWbemRefresher::Refresh menghasilkan enumerasi lengkap.

Contoh kode C++ berikut memerlukan referensi dan pernyataan #include berikut untuk dikompilasi dengan benar.

#define _WIN32_DCOM

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

Prosedur berikut menunjukkan cara menambahkan enumerator ke penyegaran.

Untuk menambahkan enumerator ke penyegaran

  1. Panggil metode IWbemConfigureRefresher::AddEnum menggunakan jalur ke objek yang dapat di-refresh dan antarmuka IWbemServices .

    Penyegar mengembalikan penunjuk ke antarmuka IWbemHiPerfEnum . Anda dapat menggunakan antarmuka IWbemHiPerfEnum untuk mengakses objek dalam enumerasi.

    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. Buat perulangan yang melakukan tindakan berikut:

Contoh

Contoh kode C++ berikut menghitung kelas berkinerja tinggi, di mana klien mengambil handel properti dari objek pertama, dan menggunakan kembali handel untuk sisa operasi refresh. Setiap panggilan ke metode Refresh memperbarui jumlah instans dan data instans.

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

Kelas Penghitung Kinerja

Mengakses Data Performa dalam Skrip

Merefresh Data WMI dalam Skrip

Tugas WMI: Pemantauan Performa

Memantau Data Performa

Kualifikasi Properti untuk Kelas Penghitung Kinerja Yang Diformat

Jenis Penghitung Kinerja WMI

Wmiadap.exe

QueryPerformanceCounter