存取 C++ 中的效能資料

WMI 高效能 API 是一系列介面,可從 效能計數器類別取得資料。 這些介面需要使用 重新整理器 物件來增加取樣率。 如需在腳本中使用重新整理器物件的詳細資訊,請參閱存取腳本和 WMI工作中的效能資料:效能監視

本主題將討論下列各節:

重新整理效能資料

重新整理器物件會藉由擷取資料而不跨越進程界限來增加資料提供者和用戶端效能。 如果用戶端和伺服器都位於同一部電腦上,重新整理程式會將高效能提供者載入用戶端,並將資料直接從提供者物件複製到用戶端物件。 如果用戶端和伺服器位於不同的電腦上,重新整理器會快取遠端電腦上的物件,並將最少的資料集傳輸至用戶端,藉以提升效能。

重新整理程式也:

  • 當發生網路錯誤或遠端電腦重新開機時,自動將用戶端重新連線到遠端 WMI 服務。

    根據預設,當兩部電腦之間的遠端連線失敗時,重新整理器會嘗試將應用程式重新連線至相關的高效能提供者。 若要防止重新連線,請在Refresh方法呼叫中傳遞WBEM_FLAG_REFRESH_NO_AUTO_RECONNECT旗標。 腳本用戶端必須將 SWbemRefresher.AutoReconnect 屬性設定為 FALSE

  • 載入相同或不同提供者所提供的多個物件和列舉值。

    可讓您將多個物件、列舉值或兩者新增至重新整理器。

  • 列舉物件。

    與其他提供者一樣,高效能提供者可以列舉物件。

完成撰寫高效能用戶端之後,您可能會想要改善回應時間。 由於 IWbemObjectAccess 介面已針對速度優化,因此介面並非內建執行緒安全。 因此,在重新整理作業期間,請勿存取可重新整理的物件或列舉。 若要在 IWbemObjectAccess 方法呼叫期間保護跨執行緒的物件,請使用 IWbemObjectAccess::LockUnlock 方法。 為了提升效能,請同步處理執行緒,讓您不需要鎖定個別執行緒。 減少執行緒和同步處理物件群組以進行重新整理作業,可提供最佳的整體效能。

將列舉值新增至 WMI 重新整理器

將列舉值新增至重新整理器,讓 每次呼叫 IWbemRefresher::Refresh 都會產生完整的列舉,以重新整理每個實例中的實例和資料數目。

下列 C++ 程式碼範例需要下列參考和#include語句才能正確編譯。

#define _WIN32_DCOM

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

下列程式示範如何將列舉值新增至重新整理器。

將列舉值新增至重新整理器

  1. 使用可重新整理物件的路徑和IWbemServices介面,呼叫IWbemConfigureRefresher::AddEnum方法。

    重新整理程式會傳回 IWbemHiPerfEnum 介面的指標。 您可以使用 IWbemHiPerfEnum 介面來存取列舉中的物件。

    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. 建立執行下列動作的迴圈:

範例

下列 C++ 程式碼範例會列舉高效能類別,其中用戶端會從第一個 物件擷取屬性控制碼,並針對重新整理作業的其餘部分重複使用控制碼。 每次呼叫 Refresh 方法時,都會更新實例數目和實例資料。

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

效能計數器類別

存取腳本中的效能資料

重新整理腳本中的 WMI 資料

WMI 工作:效能監視

監視效能資料

格式化效能計數器類別的屬性限定詞

WMI 效能計數器類型

Wmiadap.exe

QueryPerformanceCounter