Я пытаюсь раскрыть данные о производительности, используя v2.0 счетчиков производительности Windows. Я считаю, что правильно выполнил инструкции, но 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:\temp\ConsoleApplication7\Debug\ConsoleApplication7.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:\temp\ConsoleApplication7>lodctr /m:PerformanceCounters.xml
Info: Successfully installed performance counters in D:\temp\ConsoleApplication7\PerformanceCounters.xml
Это добавляет следующее в реестр:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_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:\temp\ConsoleApplication7\Debug\ConsoleApplication7.exe"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\_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 ++ сверху и сгенерированный файл .rc в мой проект C ++. Когда я его компилирую, я вижу, что строковые ресурсы действительно встроены в .exe. Программа работает нормально — ошибки не возвращаются, и я вхожу в (ненужный) цикл сообщений.
Когда я запускаю perfmon, в списке отображается мой счетчик «MyPerformanceCounterSet». Когда моя программа работает, я вижу свой экземпляр «FOO», когда выбираю набор счетчиков. Но если развернуть набор счетчиков, я вижу «Не удается загрузить счетчики».
Я администратор на этой машине. Я также являюсь членом местных групп Performance Log Users
а также Performance Monitor Users
, Я трижды проверил путь в манифесте. Если я включаю обратные вызовы (через callback="custom"
в манифесте), я получаю обратные вызовы к моему методу обратного вызова, поскольку perfmon собирает информацию. Но, тем не менее, он не может перечислить счетчики.
ОБНОВЛЕНИЕ: Я нашел образец в Windows 7 SDK (C: \ Program Files \ Microsoft SDKs \ Windows \ v7.0 \ Samples \ winbase \ PerfCounters \ Basic \ CPP). Этот пример дает тот же результат — «Не могу загрузить счетчики»
Задача ещё не решена.