从C++公开的 Windows 性能计数器始终在 perfmon 中产生"Can't load counters".exe



我正在尝试使用Windows性能计数器v2.0来暴露性能数据。我相信我已经正确地遵循了说明,但是perfmon.exe总是说"不能加载计数器"为我的计数器集。

这是我的清单,我存储在一个名为performancecounters。xml的文件

<?xml version="1.0" encoding="utf-8"?>
<instrumentationManifest xmlns="http://schemas.microsoft.com/win/2004/08/events" xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <instrumentation>
    <counters xmlns="http://schemas.microsoft.com/win/2005/12/counters" schemaVersion="1.1">
      <provider applicationIdentity="D:tempConsoleApplication7DebugConsoleApplication7.exe" providerGuid="{84C1D6C9-31BD-4B0F-BED2-F7AF3F24BEB9}" symbol="MyPerformanceCounterProvider" providerType="userMode" providerName="MyPerformanceCounterProvider">
        <counterSet uri="MyPerformanceCounterSet" symbol="MyPerformanceCounterSet" guid="{50ADA4E1-AD6B-48F0-A1A4-D87D03B8A281}" name="MyPerformanceCounterSet" description="MyPerformanceCounterSet" instances="multiple">
          <counter id="1" uri="MyPerformanceCounter1" description="MyPerformanceCounter1" type="perf_counter_large_rawcount" detailLevel="standard" />
        </counterSet>
      </provider>
    </counters>
  </instrumentation>
</instrumentationManifest>

我创建了一个。h和。rc文件通过运行:

ctrpp PerformanceCounters.xml -o PerformanceCounters.h -rc PerformanceCounters.rc
下面是我的测试代码:

#include "PerformanceCounters.h"
int _tmain(int argc, _TCHAR* argv[])
{
    auto counterInitializeResult = CounterInitialize();
    if (counterInitializeResult == ERROR_SUCCESS)
    {
        auto counterSet = PerfCreateInstance(MyPerformanceCounterProvider, &MyPerformanceCounterSetGuid, L"FOO", 1ul);
        if (counterSet != nullptr)
        {
            auto setCounterResult = PerfSetULongLongCounterValue(MyPerformanceCounterProvider, counterSet, 1ul, 23);
            if (setCounterResult == ERROR_SUCCESS)
            {
                MSG msg;
                while (GetMessage(&msg, NULL, 0, 0)) // message pump is unnecessary but it keeps the process alive
                {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
            }
            PerfDeleteInstance(MyPerformanceCounterProvider, counterSet);
            counterSet = nullptr;
        }
        CounterCleanup();
    }
    return 0;
}

我在管理员命令提示符下运行以下命令,将字符串加载到注册表中:

D:tempConsoleApplication7>lodctr /m:PerformanceCounters.xml
Info: Successfully installed performance counters in D:tempConsoleApplication7PerformanceCounters.xml

这将向注册表添加以下内容:

[HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionPerflib_V2Providers{84c1d6c9-31bd-4b0f-bed2-f7af3f24beb9}]
"ProviderType"=dword:00000000
"ProviderName"="MyPerformanceCounterProvider"
"ApplicationIdentity"=hex(2):44,00,3a,00,5c,00,74,00,65,00,6d,00,70,00,5c,00,
  43,00,6f,00,6e,00,73,00,6f,00,6c,00,65,00,41,00,70,00,70,00,6c,00,69,00,63,
  00,61,00,74,00,69,00,6f,00,6e,00,37,00,5c,00,44,00,65,00,62,00,75,00,67,00,
  5c,00,43,00,6f,00,6e,00,73,00,6f,00,6c,00,65,00,41,00,70,00,70,00,6c,00,69,
  00,63,00,61,00,74,00,69,00,6f,00,6e,00,37,00,2e,00,65,00,78,00,65,00,00,00
  ^^^^^^^^ This is actually a REG_EXPAND_SZ value that equals "D:tempConsoleApplication7DebugConsoleApplication7.exe"
[HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionPerflib_V2Providers{84c1d6c9-31bd-4b0f-bed2-f7af3f24beb9}{50ada4e1-ad6b-48f0-a1a4-d87d03b8a281}]
"NameResource"=dword:00000001
"ExplainResource"=dword:00000003
"InstanceType"=dword:00000002
"First Counter"=dword:0000302e
"NeutralName"="MyPerformanceCounterSet"
"Last Counter"=dword:00003030
"CounterBlock"=hex:01,00,00,00,00,01,01,00,00,00,00,00,00,00,00,00,64,00,00,00,
  00,00,00,00,ff,ff,ff,ff,05,00,00,00,00,00,00,00,ff,ff,ff,ff,ff,ff,ff,ff,ff,
  ff,ff,ff,ff,ff,ff,ff,00,00,00,00
"CounterCount"=dword:00000001

我已经在我的c++项目中包含了上面的c++和生成的。rc文件。当我编译它时,我看到字符串资源确实嵌入在.exe中。程序运行良好——没有返回错误,我进入了我的(不必要的)消息循环。

当我运行perfmon时,我在列表中看到我的计数器集"MyPerformanceCounterSet"。当我的程序运行时,当我选择计数器集时,我看到我的实例"FOO"。但是如果我扩展计数器集,我看到"不能加载计数器"。

我是这台机器的管理员。我也是本地团体Performance Log UsersPerformance Monitor Users的成员。我已经再三检查了清单上的路径。如果我启用回调(通过清单中的callback="custom"),我正在接收回调到我的回调方法,因为perfmon正在收集信息。但它似乎仍然不能列举计数器。

更新:我在Windows 7 SDK中找到了一个示例(C:Program FilesMicrosoft SDK Windowsv7.0SampleswinbasePerfCountersBasicCPP)。这个示例产生相同的结果——"Can't load counters"

我迟到了,但我想回答以防其他人看到这个。当我在为应用程序生成新的性能计数器时遇到同样的问题时,99.9%的时间是因为我在惰性地从一个清单复制到另一个清单时忘记生成新的guid,从而导致冲突。要纠正这个问题,为您的提供程序(providerGuid属性)和counterSet (guid属性)生成新的guid。这样,当它加载计数器时,它可以正确地执行。

相关内容