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.