Hello,
I am trying to write a program in C++ that uses performance counters with PERFLIB 2.0. I wrote a simple xml manifest which contains 3 counters - a counter, an average base and an average timer. I compiled them, included them in the code.
Now, I am trying to actually use them - but I seem to be unable to set the value of the average counter - It keeps throwing me the 87 error (incorrect parameter), even though I'm pretty sure the parameters are OK - I use them, one line above, to set the base counter, and that works fine.
I've scored the internet for documentation, for any kind of examples or help - but there isn't anything except the articles on this site, which are very high-level and rather unhelpful, and there aren't any code samples. There is some documentation for C#, but that doesn't help me.
Below is the relevant code:
The XML file:
<!-- <?xml version="1.0" encoding="UTF-16"?> --> <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 callback = "custom" symbol="TestCounters" applicationIdentity = "TestCounters.exe" providerType = "userMode" providerGuid = "{ab8e1320-965a-4cf9-9c07-fe25378c2a23}"> <counterSet guid = "{f72fdf55-eaa6-45ba-bf6d-4c7cb0d6ef73}" uri = "Microsoft.Windows.System.PerfCounters.TestCounterSet" name = "Counters Test" symbol="CountersTest" description = "Test of Counters" instances = "single"> <counter id = "1" uri = "Microsoft.Windows.System.PerfCounters.TestCounterSet.opTimeBase" name = "Operation Time base" description = "Count Operation Time Average" type = "perf_average_base" detailLevel = "standard" defaultScale = "1"> </counter> <counter id = "2" uri = "Microsoft.Windows.System.PerfCounters.TestCounterSet.opTime" name = "Operation Time" description = "Count Operation Time" type = "perf_average_timer" baseID = "1" detailLevel = "standard"> </counter> <counter id = "3" uri = "Microsoft.Windows.System.PerfCounters.TestCounterSet.countOps" name = "Count operations" description = "operations count." type = "perf_counter_counter" detailLevel = "standard" defaultScale = "1"> <counterAttributes> <counterAttribute name = "reference" /> </counterAttributes> </counter> </counterSet> </provider> </counters> </instrumentation> </instrumentationManifest>
My code:
...
ULONG countOps = 0; // The by-reference counter variable
double countAverageDuration ;
ULONG res;
res = PerfAutoInitialize();
if (res != ERROR_SUCCESS)
throw string("Failed to initialize");
PPERF_COUNTERSET_INSTANCE cinst = PerfCreateInstance(
hProvider,
&CounterSet_GUID,
L"My First Counters",
1);
if (cinst == NULL)
throw string("Could not create counter instance");
res = PerfSetCounterRefValue(
hProvider,
cinst,
3,
&countOps
);
if (res != ERROR_SUCCESS) {
throw string("Could not set counter ref value!");
}
srand(time(NULL));
while (true) {
int ops = rand() % 100000 + 2000;
for (int i = 0; i < ops; i++) {
countOps++;
int duration = rand() % 1000;
// Increase the base
res = PerfIncrementULongCounterValue(hProvider, cinst, 1, 1);
if (res != ERROR_SUCCESS)
throw string("Could not increment base average counter");
// Increase the average -- this line keeps throwing error 87
res = PerfIncrementULongCounterValue(hProvider, cinst, 2, duration);
if (res != ERROR_SUCCESS)
throw string("Could not increment average counter");
BlaBla(duration);
}
if (ops == 2000) break;
}
PerfDeleteInstance(hProvider, cinst);
PerfStopProvider(hProvider);
return 0;
Please help!
Thanks,
G.