WMI Event Watcher性能问题
问题描述:
我写过一些WMI代码,在大多数机器上运行得非常好。但是在某些机器上(几乎所有基于SSD的mac)都会导致巨大的性能问题。它导致WMIPrvSe进程继续击中I/O Other。如果您运行另一个应用程序来进行同样的观察,那么它会慢慢爬到软件无法使用的地步。WMI Event Watcher性能问题
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));
}