API

정보: 성능 카운터 및 인스턴스 열거 PDH 샘플 코드

디버그정 2012. 10. 25. 11:36

정보: 성능 카운터 및 인스턴스 열거 PDH 샘플 코드

기술 자료: 287157 - 이 문서가 적용되는 제품 보기.
모두 확대 | 모두 축소

요약

성능 데이터 도우미 (PDH) API 성능 카운터 및 인스턴스를 지정한 컴퓨터의 지정한 개체 열거하는 데 사용할 수 있습니다. 이 문서에서는 필요한 PDH API 호출 순서를 설명합니다.

추가 정보

예제 코드에서는 방법을 보여 줍니다. 성능 카운터 및 인스턴스가 지정된 개체와 구하십시오. 목록에 얻은 후에 카운터 경로를 각 인스턴스에 대해 생성된 및 성능 데이터 값을 한 번 얻을 수 있습니다.
#include <windows.h>
#include <pdh.h>
#include <pdhmsg.h>
#include <stdio.h>

void WINAPI GetCounterValues(LPTSTR serverName, LPTSTR objectName,
                             LPTSTR counterList, LPTSTR instanceList);
void WINAPI EnumerateExistingInstances(LPTSTR serverName, LPTSTR objectName);

void main(int argc, char *argv[])
{
    if (argc > 1)
    {
        // argv[1] - Server Name
        EnumerateExistingInstances(argv[1], "Thread");
    }
    else
    {
        // Local System
        EnumerateExistingInstances(NULL, "Thread");
    }
}

/////////////////////////////////////////////////////////////////////////////// 
// 
//  FUNCTION:     GetCounterValues - This function constructs a counter path
//                from the counter and instance names obtained. The constructed
//                counter path is then used to get the performance data using
//                PdhCollectQueryData.
// 
//  RETURN VALUE: none
// 
/////////////////////////////////////////////////////////////////////////////// 
void WINAPI GetCounterValues(LPTSTR serverName, LPTSTR objectName,
                             LPTSTR counterList, LPTSTR instanceList)
{
    PDH_STATUS s;

    HQUERY hQuery;

    PDH_COUNTER_PATH_ELEMENTS *cpe = NULL;
    PDH_COUNTER_PATH_ELEMENTS *cpeBeg;

    DWORD  nCounters;
    DWORD  nInstances;

    HCOUNTER *hCounter = NULL;
    HCOUNTER *hCounterPtr;

    char *counterPtr, *instancePtr;

    char szFullPath[MAX_PATH];
    DWORD cbPathSize;
    DWORD   i, j;

    BOOL  ret = FALSE;

    PDH_FMT_COUNTERVALUE counterValue;

    // Scan through the counter names to find the number of counters.
    nCounters = 0;
    counterPtr = counterList;
    while (*counterPtr)
    {
        counterPtr += strlen(counterPtr) + 1;
        nCounters++;
    }

    // Scan through the instance names to find the number of instances.
    nInstances = 0;
    instancePtr = instanceList;
    while (*instancePtr)
    {
        instancePtr += strlen(instancePtr) + 1;
        nInstances++;
    }

    if (!nCounters || !nInstances) return;

    __try
    {
        cpe = (PDH_COUNTER_PATH_ELEMENTS *)HeapAlloc(GetProcessHeap(), 0, 
                    sizeof(PDH_COUNTER_PATH_ELEMENTS) * nCounters * nInstances);
        hCounter = (HCOUNTER *)HeapAlloc(GetProcessHeap(), 0, 
                    sizeof(HCOUNTER) * nCounters * nInstances);

        if (!cpe || !hCounter) __leave;

        // Only do this once to create a query.
        if ((s = PdhOpenQuery(NULL, 0, &hQuery)) != ERROR_SUCCESS)
        {
            fprintf(stderr, "POQ failed %08x\n", s);
            __leave;
        }

        // For each instance name in the list, construct a counter path.
        cpeBeg = cpe;
        hCounterPtr = hCounter;
        for (i = 0, counterPtr = counterList; i < nCounters;
                i++, counterPtr += strlen(counterPtr) + 1)
        {
            for (j = 0, instancePtr = instanceList; j < nInstances;
                    j++,
                    instancePtr += strlen(instancePtr) + 1,
                    cpeBeg++,
                    hCounterPtr++)
            {
                cbPathSize = sizeof(szFullPath);

                cpeBeg->szMachineName = serverName;
                cpeBeg->szObjectName = objectName;
                cpeBeg->szInstanceName = instancePtr;
                cpeBeg->szParentInstance = NULL;
                cpeBeg->dwInstanceIndex = -1;
                cpeBeg->szCounterName = counterPtr;

                if ((s = PdhMakeCounterPath(cpeBeg,
                    szFullPath, &cbPathSize, 0)) != ERROR_SUCCESS)
                {
                    fprintf(stderr,"MCP failed %08x\n", s);
                    __leave;
                }

                // Add the counter path to the query.
                if ((s = PdhAddCounter(hQuery, szFullPath, 0, hCounterPtr))
                        != ERROR_SUCCESS)
                {
                    fprintf(stderr, "PAC failed %08x\n", s);
                    __leave;
                }
            }
        }

        for (i = 0; i < 2; i++)
        {
            Sleep(100);

            // Collect data as often as you need to.
            if ((s = PdhCollectQueryData(hQuery)) != ERROR_SUCCESS)
            {
                fprintf(stderr, "PCQD failed %08x\n", s);
                __leave;
            }

            if (i == 0) continue;

            // Display the performance data value corresponding to each instance.
            cpeBeg = cpe;
            hCounterPtr = hCounter;
            for (i = 0, counterPtr = counterList; i < nCounters;
                    i++, counterPtr += strlen(counterPtr) + 1)
            {
                for (j = 0, instancePtr = instanceList; j < nInstances;
                        j++,
                        instancePtr += strlen(instancePtr) + 1,
                        cpeBeg++,
                        hCounterPtr++)
                {
                    if ((s = PdhGetFormattedCounterValue(*hCounterPtr,
                        PDH_FMT_DOUBLE,
                        NULL, &counterValue)) != ERROR_SUCCESS)
                    {
                        fprintf(stderr, "PGFCV failed %08x\n", s);
                        continue;
                    }
                    printf("%s\\%s\\%s\t\t : [%3.3f]\n",
                        cpeBeg->szObjectName,
                        cpeBeg->szCounterName,
                        cpeBeg->szInstanceName,
                        counterValue.doubleValue);
                }
            }
        }

        // Remove all the performance counters from the query.
        hCounterPtr = hCounter;
        for (i = 0; i < nCounters; i++)
        {
            for (j = 0; j < nInstances; j++)
            {
                PdhRemoveCounter(*hCounterPtr);
            }
        }
    }
    __finally
    {
        HeapFree(GetProcessHeap(), 0, cpe);
        HeapFree(GetProcessHeap(), 0, hCounter);

        // Only do this cleanup once.
        PdhCloseQuery(hQuery);
    }

    return;
}

/////////////////////////////////////////////////////////////////////////////// 
// 
//  FUNCTION:     EnumerateExistingInstances - This function displays the names
//                of all the instances that exist on ServerName. PDH is used
//                to enumerate the performance counter and instance names.
// 
//  RETURN VALUE: none
// 
/////////////////////////////////////////////////////////////////////////////// 

void WINAPI EnumerateExistingInstances(LPTSTR serverName, LPTSTR objectName)
{
    TCHAR       mszEmptyList[2];  // An empty list contains 2 NULL characters
    LPTSTR      mszInstanceList = NULL;
    LPTSTR      szInstanceName;
    DWORD       cchInstanceList;
    LPTSTR      mszCounterList = NULL;
    DWORD       cchCounterList;
    PDH_STATUS  pdhStatus;

    __try
    {
        mszCounterList = NULL;
        cchCounterList = 0;
        // Refresh the list of performance objects available on the specified
        // computer by making a call to PdhEnumObjects with bRefresh set to TRUE.
        pdhStatus = PdhEnumObjects(NULL, serverName, mszCounterList,
            &cchCounterList, PERF_DETAIL_WIZARD, TRUE);

        mszCounterList = NULL;
        cchCounterList = 0;
        // Determine the required size for the buffer containing counter names
        // and instance names by calling PdhEnumObjectItems.
        cchInstanceList = sizeof(mszEmptyList);
        pdhStatus = PdhEnumObjectItems(NULL, serverName,
            objectName, mszCounterList, 
            &cchCounterList, mszEmptyList,
            &cchInstanceList, PERF_DETAIL_WIZARD, 0);

        if (pdhStatus == ERROR_SUCCESS)
            return;  // The list is empty so do nothing.
        else if (pdhStatus != PDH_MORE_DATA)
        {
            fprintf(stderr, "PEOI failed %08x\n", pdhStatus);
            return;
        }

        // Allocate a buffer for the counter names.
        mszCounterList = (LPTSTR)HeapAlloc(GetProcessHeap(),
            HEAP_ZERO_MEMORY, cchCounterList);
        if (!mszCounterList)
        {
            fprintf(stderr, "HA failed %08x\n", GetLastError());
            return;
        }

        // Allocate a buffer for the instance names.
        mszInstanceList = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
            cchInstanceList);
        if (!mszInstanceList)
        {
            fprintf(stderr, "HA failed %08x\n", GetLastError());
            return;
        }

        __try
        {
            // Enumerate to get the list of Counters and Instances provided by
            // the specified object on the specified computer.
            pdhStatus = PdhEnumObjectItems(NULL, serverName,
                objectName, mszCounterList, 
                &cchCounterList, mszInstanceList,
                &cchInstanceList, PERF_DETAIL_WIZARD, 0);
            if (pdhStatus != ERROR_SUCCESS)
            {
                fprintf(stderr, "PEOI failed %08x\n", pdhStatus);
                return;
            }

            // Display the items from the buffer.
            szInstanceName = mszInstanceList;
            while (*szInstanceName)
            {
                printf("%s\n", szInstanceName);
                szInstanceName += strlen(szInstanceName) + 1;
            }

            GetCounterValues(serverName, objectName, mszCounterList,
                mszInstanceList);
        }
        __finally
        {
        }

    }
    __finally
    {
        // Free the buffers.
        if (mszInstanceList) HeapFree(GetProcessHeap(), 0, mszInstanceList);
        if (mszCounterList) HeapFree(GetProcessHeap(), 0, mszCounterList);
    }

    return;   
}
				

참조

Windows 2000 운영 체제에 포함되어 있는 Pdh.dll 파일을 PDH API가 구현됩니다. 운영 체제를 Windows NT 4.0에 대해 별도의 재배포 가능 Pdh.dll 버전을 다운로드할 수 있습니다.

Windows NT 4.0 Pdh.dll 재배포 가능한 버전을 구하는 방법에 대한 자세한 내용은 Microsoft 기술 자료의 다음 문서를 참조하십시오.
284996 FILE: 최신 재배포 가능한 PDH.DLL Windows NT 4 .0용
PDH API에 대한 자세한 내용은 MSDN Library 웹 사이트의 다음 항목을 참조하십시오.
성능 데이터 도우미
http://msdn.microsoft.com/en-us/library/aa373046(VS.85).aspx

속성

기술 자료: 287157 - 마지막 검토: 2006년 11월 21일 화요일 - 수정: 5.3
본 문서의 정보는 다음의 제품에 적용됩니다.
  • Microsoft Win32 Application Programming Interface 을(를) 다음과 함께 사용했을 때
    • Microsoft Windows NT 4.0
    • the operating system: Microsoft Windows 2000
    • the operating system: Microsoft Windows XP
키워드: 
kbmt kbapi kbinfo kbkernbase kbperfmon KB287157 KbMtko
기계 번역된 문서
중요: 본 문서는 전문 번역가가 번역한 것이 아니라 Microsoft 기계 번역 소프트웨어로 번역한 것입니다. Microsoft는 번역가가 번역한 문서 및 기계 번역된 문서를 모두 제공하므로 Microsoft 기술 자료에 있는 모든 문서를 한글로 접할 수 있습니다. 그러나 기계 번역 문서가 항상 완벽한 것은 아닙니다. 따라서 기계 번역 문서에는 마치 외국인이 한국어로 말할 때 실수를 하는 것처럼 어휘, 구문 또는 문법에 오류가 있을 수 있습니다. Microsoft는 내용상의 오역 또는 Microsoft 고객이 이러한 오역을 사용함으로써 발생하는 부 정확성, 오류 또는 손해에 대해 책임을 지지 않습니다. Microsoft는 이러한 문제를 해결하기 위해 기계 번역 소프트웨어를 자주 업데이트하고 있습니다.