备忘一下改功能,主要通过WMI来实现,对于监听外接设备的弹出和插入事件一开始使用IntPtr WndProc事件,但是当监听到改事件时,同过WMI来获取设备,有时候还不能获取到,因此还是使用WqlEventQuery 来监听WMI的变化。下列是主要代码片段
1. 获取硬盘的固件序列号,盘序列号(由系统指派的唯一ID),总容量,剩余容量, 盘符,盘名称等信息
private static List<DriverBase> GetDrivers(InterfaceType type, string partitionName) { List<DriverBase> drivers = new List<DriverBase>(); string strQuery = "select * from Win32_DiskDrive"; if(type == InterfaceType.USB) strQuery += " Where InterfaceType = 'USB'"; else if (type == InterfaceType.IDE) strQuery += " Where InterfaceType = 'IDE'"; SelectQuery sq = new SelectQuery(strQuery); ManagementObjectSearcher mos = new ManagementObjectSearcher(sq); foreach (ManagementObject disk in mos.Get()) { string DeviceID = disk["DeviceID"].ToString(); foreach (ManagementObject partition in new ManagementObjectSearcher("ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + DeviceID + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition").Get()) { string query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + partition["DeviceID"] + "'} WHERE AssocClass = Win32_LogicalDiskToPartition"; foreach (ManagementObject disk1 in new ManagementObjectSearcher(query).Get()) { DriverBase b = new DriverBase(); string diviceID = disk1["DeviceID"].ToString().Trim(); if (!IsNTFS(diviceID)) { continue; } string Name = disk1["Name"].ToString().Trim(); string freeSpace = disk1["FreeSpace"].ToString().Trim(); string size = disk1["Size"].ToString().Trim(); if (!string.IsNullOrEmpty(partitionName) && Name.ToUpper() != partitionName.ToUpper()) { continue; } b.DriverName = Helper.DriverHelper.GetVolumnLabel(diviceID); b.TotalSpace = double.Parse(size); b.FreeSpace = double.Parse(freeSpace); b.DeviceID = diviceID; b.IsOverload = (b.TotalSpace - b.FreeSpace) / b.TotalSpace > 0.7; b.SerialNum = disk["SerialNumber"] == null ? "" : disk["SerialNumber"].ToString().Trim(); if (string.IsNullOrEmpty(b.SerialNum)) { string pnpdeviceid = disk["PNPDeviceID"] == null ? "" : disk["PNPDeviceID"].ToString().Trim(); if (!string.IsNullOrEmpty(pnpdeviceid)) b.SerialNum = parseSerialFromDeviceID(pnpdeviceid); } b.VolumeSerialNum = GetVolumeSerialNumber(diviceID); if(!string.IsNullOrEmpty(b.SerialNum)) drivers.Add(b); } } } return drivers; } /// <summary> /// Get driver by partition name /// </summary> /// <param name="name">name should be "C:" or "D"</param> /// <returns></returns> public static DriverBase GetDriverByName(string name) { string strQuery = "select * from Win32_LogicalDisk where DeviceID='" + name + "'"; SelectQuery sq = new SelectQuery(strQuery); ManagementObjectSearcher mos = new ManagementObjectSearcher(sq); DriverBase driver = null; foreach (ManagementObject disk in mos.Get()) { driver = new DriverBase(); driver.DeviceID = disk["DeviceID"].ToString(); driver.DriverName = disk["VolumeName"].ToString(); driver.VolumeSerialNum = disk["VolumeSerialNumber"].ToString(); driver.TotalSpace = double.Parse(disk["Size"].ToString()); if (disk["FileSystem"].ToString() != "NTFS") { return null; } driver.FreeSpace = double.Parse(disk["FreeSpace"].ToString()); driver.IsOverload = (driver.TotalSpace - driver.FreeSpace) / driver.TotalSpace > 0.7; driver.SerialNum = GetSeiralByDevice(driver.DeviceID); if (!string.IsNullOrEmpty(driver.SerialNum)) return driver; } return driver; //return DriverBase.GetDrivers(InterfaceType.ALL, name).FirstOrDefault(); } // fix cannot get serial number of some flash driver of WMI // http://stackoverflow.com/questions/1176053/read-usb-device-serial-number-in-c-sharp/1176089#1176089 private static string parseSerialFromDeviceID(string deviceId) { string[] splitDeviceId = deviceId.Split('\'); string[] serialArray; string serial; int arrayLen = splitDeviceId.Length - 1; serialArray = splitDeviceId[arrayLen].Split('&'); serial = serialArray[0]; return serial; }
2. 下列代码段用于监听新增或删除外接设备
public class UsbDriverWatcher { ManagementEventWatcher eventWatcher; ManagementEventWatcher delEventWatcher; public void Start() { try { //DriveType //Value Meaning //0 Unknown //1 No Root Directory //2 Removable Disk //3 Local Disk //4 Network Drive //5 Compact Disc //6 RAM Disk WqlEventQuery query = new WqlEventQuery("__InstanceCreationEvent", new TimeSpan(0, 0, 1), @"TargetInstance ISA 'Win32_LogicalDisk'"); ConnectionOptions opt = new ConnectionOptions(); opt.EnablePrivileges = true; opt.Authority = null; opt.Authentication = AuthenticationLevel.Default; ManagementScope scope = new ManagementScope("\root\CIMV2", opt); eventWatcher = new ManagementEventWatcher(scope, query); eventWatcher.EventArrived += new EventArrivedEventHandler(eventWatcher_EventArrived); eventWatcher.Start(); WqlEventQuery delQuery = new WqlEventQuery("__InstanceDeletionEvent", new TimeSpan(0, 0, 1), @"TargetInstance ISA 'Win32_LogicalDisk'"); ConnectionOptions opt2 = new ConnectionOptions(); opt2.EnablePrivileges = true; opt2.Authority = null; opt2.Authentication = AuthenticationLevel.Default; ManagementScope scope2 = new ManagementScope("\root\CIMV2", opt2); delEventWatcher = new ManagementEventWatcher(scope2, delQuery); delEventWatcher.EventArrived += new EventArrivedEventHandler(delEventWatcher_EventArrived); delEventWatcher.Start(); } catch (Exception ex) { } } public void Stop() { if (eventWatcher != null) { eventWatcher.Stop(); delEventWatcher.Stop(); } } void eventWatcher_EventArrived(object sender, EventArrivedEventArgs e) { ManagementBaseObject wmiDevice = (ManagementBaseObject)e.NewEvent["TargetInstance"]; String driveName = (string)wmiDevice["DeviceID"]; //string volumeName = wmiDevice.Properties["VolumeName"].Value == null ? "":wmiDevice.Properties["VolumeName"].Value.ToString(); if (!string.IsNullOrEmpty(driveName)) { if (OnDeviceChanged != null) { OnDeviceChanged(null, new DeviceChangedEventArgs() { DriverName = driveName, Action = DeviceChangedAction.Add }); } } } void delEventWatcher_EventArrived(object sender, EventArrivedEventArgs e) { ManagementBaseObject wmiDevice = (ManagementBaseObject)e.NewEvent["TargetInstance"]; String driveName = (string)wmiDevice["DeviceID"]; string volumeName = wmiDevice.Properties["VolumeName"].Value == null? "" : wmiDevice.Properties["VolumeName"].Value.ToString(); if (!string.IsNullOrEmpty(driveName)) { if (OnDeviceChanged != null) { OnDeviceChanged(null, new DeviceChangedEventArgs() { DriverName = driveName, Action = DeviceChangedAction.Remove }); } } } public event DeviceChangedEventHandler OnDeviceChanged; }
//使用方法
watcher = new UsbDriverWatcher();
watcher.OnDeviceChanged += watcher_OnDeviceChanged;
watcher.Start();
3、 使用WndProc方法来监听外接设备变化的方法:
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { Handle messages... if (msg == WM_DEVICECHANGE) { App.Log.WriteInfo("Device change message received in WndProc."); if (!ViewModelLocator.Main._loading) { // need to start a new thread to load driver list // http://stackoverflow.com/questions/3921661/disconnectedcontext-mda-when-calling-wmi-functions-in-single-threaded-applicatio System.Threading.Thread t = new System.Threading.Thread(ViewModelLocator.Main.LoadDrivers); t.Start(); } } return IntPtr.Zero; }