c# 获取移动硬盘信息、监听移动设备的弹出与插入事件

备忘一下改功能,主要通过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;
        }

 

posted @ 2013-09-18 17:37  Chris Cheung  阅读(11217)  评论(5编辑  收藏  举报