Technical details:
If you attempt to load a performance counter with this code (existing Performance Object, non-existant counter):
PerformanceCounter newCounter = new PerformanceCounter("RealCategory","BogusName","Foo",true);
You'll get the very helpful error message: "Counter 'BogusName' does not exist in the specified Category."
If you use this code (non-existant Performance Object):
PerformanceCounter newCounter = new PerformanceCounter("BogusCategory","BogusName","Foo",true);
You'll get a slightly less helpful error message: "Category does not exist." . . . hmm . . would have been nice to know which category.
Now if you use that same call, but flip the readonly flag to false
PerformanceCounter newCounter = new PerformanceCounter("BogusCategory","BogusName","Foo",false);
You get this very unhelpful message: "The requested Performance Counter is not a custom counter, it has to be initialized as ReadOnly."
The trick at this point is figuring out who's trying to load a counter, and which one they're trying to load. The following code will locate a PerformanceCounterInstaller within an assembly, given a filename. Easy enough to list all the DLLs in a given space with DIR /S /B *.DLL, then run InstallUtil on the ones that turn up positive.
System.Reflection.Assembly assy = System.Reflection.Assembly.LoadFile(fileName);
Type[] publicTypes = assy.GetExportedTypes();
foreach (Type t in publicTypes)
{
if (t.BaseType.Name == "Installer")
{
Installer o = (Installer)t.Assembly.CreateInstance(t.FullName);
foreach(Installer i in o.Installers)
{
if (i.GetType().Name == "PerformanceCounterInstaller")
{
MessageBox.Show("Performance Counter Installer Found in Assembly " + fileName);
}
}
}
}