|
 |
 |
 |
 |
Microsoft Knowledge Base Article
This article contents is Microsoft Copyrighted material.
©2005-©2007 Microsoft Corporation. All rights reserved. Terms
of Use |
Trademarks
Article ID: 307515 - Last Review: October 29, 2004 - Revision: 5.1 FIX: Custom performance counters do not publish performance data to WMIThis article was previously published under Q307515
Custom performance counters that are exposed when you use the PerformanceCounter class in the System.Diagnostics namespace do not publish performance data to Windows Management Instrumentation (WMI) as expected.
Additionally, you are unable to view the .NET CLR counter and .NET Networking counter through WMI.
This behavior occurs because the following circumstances prevent the WMI schemas from being generated correctly:
The sequence followed by PerfMon- Loads the perf DLL (each DLL being specific to a given counter).Calls the Open function.For each registry key, calls the Global function.Calls the Close function.
- Calls the Open function.For each registry key, calls the Global function.Calls the Close function.
- For each registry key, calls the Global function.Calls the Close function.
- Calls the Close function.
The sequence followed by WMI (when generating the schema; only for new registry keys)- Loads the perf DLL.Calls Open.Calls Global.Calls the Costly function.Calls Close.
- Calls Open.Calls Global.Calls the Costly function.Calls Close.
- Calls Global.Calls the Costly function.Calls Close.
- Calls the Costly function.Calls Close.
- Calls Close.
When a global query is executed, it is easy to return the right object type for each Global collect call (for PerfMon or anything that relies on the RegQueryValueEx function or PDH), because the performance DLL knows exactly how many object types that the .NET PerformanceCounters component provides and how many times the collect call will be called. Therefore, the objects are returned in sequence.
To resolve this problem, install the hotfix in the following Microsoft Knowledge Base article, and then run the C# code that follows: 824336Â
(http://kbalertz.com/Feedback.aspx?kbNumber=824336/
)
FIX: Custom performance counters do not publish performance data to WMI
C# codeNote You can either incorporate the C# code into released projects or run the C# code as a stand-alone application. For executing the C# code or utility, you must pass in the names of all categories that are multi-instance. using System;
using Microsoft.Win32;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Globalization;
using System.ServiceProcess;
using System.ComponentModel;
using System.Threading;
namespace FixPerfCounters {
public class FixCounters {
public static void Main(string[] args) {
if (args.Length > 0 && (args[0] == "http://support.microsoft.com/?" || args[0] == "-?")) {
Console.WriteLine("Usage: " + Environment.GetCommandLineArgs()[0] + " [<category> <category2> ...]");
Console.WriteLine("\tWhere <category>, <category2>, etc., are categories which will be used with multi instance counters.");
return;
}
Console.WriteLine("Fixing up old custom counters...");
FixPerfCounters();
Console.WriteLine("Setting new counters as MultiInstance...");
SetMultiInstance(args);
Console.WriteLine("Restarting Winmgmt...");
RestartWingmgmt();
Console.WriteLine("Resyncing WMI cache...");
ResyncWMI();
Console.WriteLine("Done.");
}
internal static void FixPerfCounters() {
RegistryKey servicesKey = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services");
string[] servicesSubKeyNames = servicesKey.GetSubKeyNames();
foreach (string subKeyName in servicesSubKeyNames) {
RegistryKey perfObjectKey = servicesKey.OpenSubKey(subKeyName, true);
RegistryKey performanceKey = perfObjectKey.OpenSubKey("Performance", true);
if (performanceKey != null) {
if ( ((string) performanceKey.GetValue("library")) == "netfxperf.dll") {
RegistryKey linkageKey = perfObjectKey.CreateSubKey("Linkage");
int index = perfObjectKey.Name.LastIndexOf("\\");
linkageKey.SetValue("Export", new string[] { perfObjectKey.Name.Substring(index + 1)} );
linkageKey.Close();
performanceKey.SetValue("WbemAdapStatus", 0);
}
performanceKey.Close();
}
perfObjectKey.Close();
}
servicesKey.Close();
}
internal static void SetMultiInstance(string[] args) {
RegistryKey categoryKey;
foreach (string category in args) {
categoryKey = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Services\\" + category + "\\Performance", true);
if (categoryKey != null) {
Console.WriteLine(category);
categoryKey.SetValue("IsMultiInstance", 1);
categoryKey.Close();
}
else
Console.WriteLine("Category '" + category + "' does not exist");
}
categoryKey = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Services\\.NET CLR Data\\Performance", true);
if (categoryKey != null) {
categoryKey.SetValue("IsMultiInstance", 1);
categoryKey.Close();
}
categoryKey = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Services\\.NET CLR Networking\\Performance", true);
if (categoryKey != null) {
categoryKey.SetValue("IsMultiInstance", 1);
categoryKey.Close();
}
}
internal static void RestartWingmgmt() {
ServiceController winmgmt = new ServiceController("winmgmt");
if (winmgmt.Status != ServiceControllerStatus.Stopped && winmgmt.Status != ServiceControllerStatus.StopPending )
winmgmt.Stop();
winmgmt.WaitForStatus(ServiceControllerStatus.Stopped);
winmgmt.Start();
winmgmt.WaitForStatus(ServiceControllerStatus.Running);
// wait to ensure that wmiadap is not running
Thread.Sleep(5000);
}
internal static int GetWinmgmtPid() {
IntPtr serviceManagerHandle = OpenSCManager(null, null, SC_MANAGER_ENUMERATE_SERVICE);
IntPtr serviceHandle = OpenService(serviceManagerHandle, "winmgmt", SERVICE_QUERY_STATUS);
if (serviceHandle == (IntPtr)0) {
throw new Win32Exception();
}
SERVICE_STATUS_PROCESS serviceStatus = new SERVICE_STATUS_PROCESS();
byte[] buffer = new byte[1000];
int bytesNeeded;
GCHandle bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
bool success = QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO, buffer, 1000, out bytesNeeded);
if (!success)
throw new Win32Exception();
IntPtr buffIntPtr = bufferHandle.AddrOfPinnedObject();
Marshal.PtrToStructure( buffIntPtr, serviceStatus);
}
finally {
bufferHandle.Free();
}
CloseServiceHandle(serviceHandle);
CloseServiceHandle(serviceManagerHandle);
return serviceStatus.dwProcessId;
}
internal static void ResyncWMI() {
OperatingSystem os = Environment.OSVersion;
if (os.Version < new Version(5, 1)) {
// Windows 2000 case
string pid = GetWinmgmtPid().ToString(CultureInfo.InvariantCulture);
Process p = Process.Start("winmgmt.exe", "/resyncperf " + pid);
p.WaitForExit();
}
else {
// Windows XP case
ProcessIdleTasks();
Thread.Sleep(1000);
Process p = Process.Start("wmiadap.exe", "/F");
p.WaitForExit();
}
}
internal const int SC_MANAGER_ENUMERATE_SERVICE = 0x0004;
internal const int SERVICE_QUERY_STATUS = 0x0004;
internal const int SC_STATUS_PROCESS_INFO = 0;
[DllImport("advapi32.dll", CharSet=System.Runtime.InteropServices.CharSet.Unicode, SetLastError=true)]
internal extern static IntPtr OpenSCManager(string machineName, string databaseName, int access);
[DllImport("advapi32.dll", CharSet=System.Runtime.InteropServices.CharSet.Unicode, SetLastError=true)]
internal static extern bool QueryServiceStatusEx (IntPtr serviceHandle, int InfoLevel, byte[] lpBuffer, int cbBufSize, out int pcbBytesNeeded);
[DllImport("advapi32.dll", CharSet=System.Runtime.InteropServices.CharSet.Unicode, SetLastError=true)]
internal extern static bool CloseServiceHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet=System.Runtime.InteropServices.CharSet.Unicode, SetLastError=true)]
internal extern static IntPtr OpenService(IntPtr databaseHandle, string serviceName, int access);
[DllImport("advapi32.dll", SetLastError=true)]
internal extern static int ProcessIdleTasks();
}
[StructLayout(LayoutKind.Sequential)]
internal class SERVICE_STATUS_PROCESS {
public int dwServiceType = 0;
public int dwCurrentState = 0;
public int dwControlsAccepted = 0;
public int dwWin32ExitCode = 0;
public int dwServiceSpecificExitCode = 0;
public int dwCheckPoint = 0;
public int dwWaitHint = 0;
public int dwProcessId = 0;
public int dwServiceFlags = 0;
}
}
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.
This bug was corrected in Microsoft Visual Studio .NET (2003).
APPLIES TO- Microsoft .NET Framework 1.0
- Microsoft Windows Management Instrumentation in . NET
| kbbug kbfix kbreadme KB307515 |
Community Feedback System
Very often, it takes hours to solve a problem. Very often, you've looked high
and low, and have tried a lot of solutions. When you finally found it, chances
are, it was because someone else helped you. Here's your chance to give back.
Use our community feedback tool to let others know what worked for you and what
didn't.
Please also understand that the community feedback system is not warranted to be
correct, it's simply a system that we've built to let people try and help each
other. If something in a feedback response doesn't make sense to you, or you're
not comfortable making changes that the feedback talks about (like registry
edits), please consult a professional.
Thank you for using kbAlertz.com Feedback System.
-- Scott Cate
|
 |
 |
 |
 |
 |
 |
 |
| |