WMI 事件观察器性能问题
WMI Event Watcher Performance Problems
我编写了一些在大多数机器上运行良好的 WMI 代码。但是在某些机器上(几乎所有基于 SSD 的 mac),此代码会导致巨大的性能问题。它会导致 WMIPrvSe 进程不断命中 I/O 其他。如果您 运行 另一个应用程序进行相同的观看,那么它会变慢到爬行到软件变得无法使用的程度。
System.Management.WqlEventQuery queryIn;
System.Management.WqlEventQuery queryOut;
System.Management.ManagementScope scope = new System.Management.ManagementScope( "root\CIMV2" );
scope.Options.EnablePrivileges = true;
try
{
queryIn = new System.Management.WqlEventQuery();
queryIn.EventClassName = "__InstanceCreationEvent";
queryIn.WithinInterval = new TimeSpan( 0, 0, 1 );
//queryIn.GroupWithinInterval = new TimeSpan( 0, 0, 0 );
queryIn.Condition = @"TargetInstance ISA 'Win32_DiskDrive' AND TargetInstance.InterfaceType = 'USB'";
mUSBWatcherIn = new System.Management.ManagementEventWatcher( scope, queryIn );
//adds event handler that’s is fired when the insertion event occurs
mUSBWatcherIn.EventArrived += new System.Management.EventArrivedEventHandler( USBInserted );
queryOut = new System.Management.WqlEventQuery();
queryOut.EventClassName = "__InstanceDeletionEvent";
queryOut.WithinInterval = new TimeSpan( 0, 0, 1 );
//queryOut.GroupWithinInterval = new TimeSpan( 0, 0, 0 );
queryOut.Condition = @"TargetInstance ISA 'Win32_DiskDrive' AND TargetInstance.InterfaceType = 'USB'";
mUSBWatcherOut = new System.Management.ManagementEventWatcher( scope, queryOut );
//adds event handler that’s is fired when the insertion event occurs
mUSBWatcherOut.EventArrived += new System.Management.EventArrivedEventHandler( USBRemoved );
mUSBWatcherIn.Start();//run the watcher
mUSBWatcherOut.Start();
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show( e.Message );
StopUSBWatcher();
}
有人知道这里会发生什么吗?如果我删除这段代码,那么它就可以完美运行。在其他机器上,它工作得很好。这很奇怪。非常感谢任何想法!
所以我还没有找出导致问题的原因,但我现在已经使用 WM_DEVICECHANGE.
实现了相同的功能
这是我的互操作设置:
[System.Runtime.InteropServices.DllImport( "user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall )]
private static extern IntPtr RegisterDeviceNotification(IntPtr recipient, IntPtr notificationFilter, int flags);
[System.Runtime.InteropServices.DllImport( "user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall )]
private static extern bool UnregisterDeviceNotification(IntPtr handle);
[System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
static extern IntPtr GetWindowLongPtr( IntPtr hWnd, int nIndex );
[System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
static extern int GetWindowLong( IntPtr hWnd, int nIndex );
[System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
static extern IntPtr SetWindowLongPtr( IntPtr hWnd, int nIndex, IntPtr newLong );
[System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
static extern int SetWindowLong( IntPtr hWnd, int nIndex, int newLong );
delegate IntPtr WndProcDelegate( IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam );
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr CallWindowProc( IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam );
public const int GWLP_WNDPROC = -4;
[System.Runtime.InteropServices.StructLayout( System.Runtime.InteropServices.LayoutKind.Sequential )]
private struct DevBroadcastDeviceinterface
{
internal int Size;
internal int DeviceType;
internal int Reserved;
internal Guid ClassGuid;
internal short Name;
}
const int DBT_DEVTYPVOLUME = 0x00000002;
const int DBT_DEVTYPDEVICEINTERFACE = 5;
static readonly Guid GuidDevinterfaceUSBDevice = new Guid( "A5DCBF10-6530-11D2-901F-00C04FB951ED" );
而实际的设置代码如下:
DevBroadcastDeviceinterface dbi = new DevBroadcastDeviceinterface
{
DeviceType = DBT_DEVTYPDEVICEINTERFACE,//DBT_DEVTYPVOLUME,
Reserved = 0,
ClassGuid = GuidDevinterfaceUSBDevice,
Name = 0
};
dbi.Size = System.Runtime.InteropServices.Marshal.SizeOf( dbi );
IntPtr buffer = System.Runtime.InteropServices.Marshal.AllocHGlobal( dbi.Size );
System.Runtime.InteropServices.Marshal.StructureToPtr( dbi, buffer, true );
IntPtr i = RegisterDeviceNotification( Handle, buffer, 0 );
System.Runtime.InteropServices.Marshal.FreeHGlobal( buffer );
if ( IntPtr.Size == 4 )
{
oldWndProc = new IntPtr( SetWindowLong( Handle, GWLP_WNDPROC, System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate( newWndProc ).ToInt32() ) );
}
else
{
oldWndProc = SetWindowLongPtr( Handle, GWLP_WNDPROC, System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate( newWndProc ) );
}
我编写了一些在大多数机器上运行良好的 WMI 代码。但是在某些机器上(几乎所有基于 SSD 的 mac),此代码会导致巨大的性能问题。它会导致 WMIPrvSe 进程不断命中 I/O 其他。如果您 运行 另一个应用程序进行相同的观看,那么它会变慢到爬行到软件变得无法使用的程度。
System.Management.WqlEventQuery queryIn;
System.Management.WqlEventQuery queryOut;
System.Management.ManagementScope scope = new System.Management.ManagementScope( "root\CIMV2" );
scope.Options.EnablePrivileges = true;
try
{
queryIn = new System.Management.WqlEventQuery();
queryIn.EventClassName = "__InstanceCreationEvent";
queryIn.WithinInterval = new TimeSpan( 0, 0, 1 );
//queryIn.GroupWithinInterval = new TimeSpan( 0, 0, 0 );
queryIn.Condition = @"TargetInstance ISA 'Win32_DiskDrive' AND TargetInstance.InterfaceType = 'USB'";
mUSBWatcherIn = new System.Management.ManagementEventWatcher( scope, queryIn );
//adds event handler that’s is fired when the insertion event occurs
mUSBWatcherIn.EventArrived += new System.Management.EventArrivedEventHandler( USBInserted );
queryOut = new System.Management.WqlEventQuery();
queryOut.EventClassName = "__InstanceDeletionEvent";
queryOut.WithinInterval = new TimeSpan( 0, 0, 1 );
//queryOut.GroupWithinInterval = new TimeSpan( 0, 0, 0 );
queryOut.Condition = @"TargetInstance ISA 'Win32_DiskDrive' AND TargetInstance.InterfaceType = 'USB'";
mUSBWatcherOut = new System.Management.ManagementEventWatcher( scope, queryOut );
//adds event handler that’s is fired when the insertion event occurs
mUSBWatcherOut.EventArrived += new System.Management.EventArrivedEventHandler( USBRemoved );
mUSBWatcherIn.Start();//run the watcher
mUSBWatcherOut.Start();
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show( e.Message );
StopUSBWatcher();
}
有人知道这里会发生什么吗?如果我删除这段代码,那么它就可以完美运行。在其他机器上,它工作得很好。这很奇怪。非常感谢任何想法!
所以我还没有找出导致问题的原因,但我现在已经使用 WM_DEVICECHANGE.
实现了相同的功能这是我的互操作设置:
[System.Runtime.InteropServices.DllImport( "user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall )]
private static extern IntPtr RegisterDeviceNotification(IntPtr recipient, IntPtr notificationFilter, int flags);
[System.Runtime.InteropServices.DllImport( "user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall )]
private static extern bool UnregisterDeviceNotification(IntPtr handle);
[System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
static extern IntPtr GetWindowLongPtr( IntPtr hWnd, int nIndex );
[System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
static extern int GetWindowLong( IntPtr hWnd, int nIndex );
[System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
static extern IntPtr SetWindowLongPtr( IntPtr hWnd, int nIndex, IntPtr newLong );
[System.Runtime.InteropServices.DllImport( "user32.dll", SetLastError = true )]
static extern int SetWindowLong( IntPtr hWnd, int nIndex, int newLong );
delegate IntPtr WndProcDelegate( IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam );
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr CallWindowProc( IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam );
public const int GWLP_WNDPROC = -4;
[System.Runtime.InteropServices.StructLayout( System.Runtime.InteropServices.LayoutKind.Sequential )]
private struct DevBroadcastDeviceinterface
{
internal int Size;
internal int DeviceType;
internal int Reserved;
internal Guid ClassGuid;
internal short Name;
}
const int DBT_DEVTYPVOLUME = 0x00000002;
const int DBT_DEVTYPDEVICEINTERFACE = 5;
static readonly Guid GuidDevinterfaceUSBDevice = new Guid( "A5DCBF10-6530-11D2-901F-00C04FB951ED" );
而实际的设置代码如下:
DevBroadcastDeviceinterface dbi = new DevBroadcastDeviceinterface
{
DeviceType = DBT_DEVTYPDEVICEINTERFACE,//DBT_DEVTYPVOLUME,
Reserved = 0,
ClassGuid = GuidDevinterfaceUSBDevice,
Name = 0
};
dbi.Size = System.Runtime.InteropServices.Marshal.SizeOf( dbi );
IntPtr buffer = System.Runtime.InteropServices.Marshal.AllocHGlobal( dbi.Size );
System.Runtime.InteropServices.Marshal.StructureToPtr( dbi, buffer, true );
IntPtr i = RegisterDeviceNotification( Handle, buffer, 0 );
System.Runtime.InteropServices.Marshal.FreeHGlobal( buffer );
if ( IntPtr.Size == 4 )
{
oldWndProc = new IntPtr( SetWindowLong( Handle, GWLP_WNDPROC, System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate( newWndProc ).ToInt32() ) );
}
else
{
oldWndProc = SetWindowLongPtr( Handle, GWLP_WNDPROC, System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate( newWndProc ) );
}