Click here to Skip to main content
15,891,423 members
Articles / Desktop Programming / WPF

C.B.R.

Rate me:
Please Sign up or sign in to vote.
4.96/5 (52 votes)
22 Oct 2012GPL329 min read 124.9K   1.8K   132  
Comic and electronic publication reader with library management, extended file conversion, and devices support.
using System;
using System.Management;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Threading;
using System.Threading;

namespace CBR.Core.Helpers
{
    #region ----------------EVENTS----------------

    public enum WMIActions
    {
        Added,
        Removed
    }

    public class WMIEventArgs : EventArgs
    {
        public USBDiskInfo Disk { get; set; }
        public WMIActions EventType { get; set; }
    }

    public delegate void WMIEventArrived(object sender, WMIEventArgs e);

    #endregion

    /// <summary>
    /// 
    /// </summary>
    public class WMIEventWatcher
    {
        #region ----------------CONSTRUCTOR----------------

        /// <summary>
        /// constructor
        /// </summary>
        public WMIEventWatcher()
        {
            Devices = GetExistingDevices();
        }

        #endregion

        #region ----------------INTERNALS----------------

        /// <summary>
        /// internal watcher for add event
        /// </summary>
        private ManagementEventWatcher addedWatcher = null;

        /// <summary>
        /// internal watcher for remove event
        /// </summary>
        private ManagementEventWatcher removedWatcher = null;

        #endregion

        #region ----------------PROPERTIES----------------

        /// <summary>
        /// List of founded devices
        /// </summary>
        public List<USBDiskInfo> Devices { get; set; }

        #endregion

        #region ----------------EVENTS----------------

        /// <summary>
        /// signaled when watched events occurs
        /// </summary>
        public event WMIEventArrived EventArrived;

        #endregion

        #region ----------------METHODS----------------

        /// <summary>
        /// start watching for logical device events
        /// </summary>
        public void StartWatchUSB()
        {
            try
            {
                addedWatcher = new ManagementEventWatcher("SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA \"Win32_USBControllerDevice\"");
                addedWatcher.EventArrived += new EventArrivedEventHandler(HandleAddedEvent);
                addedWatcher.Start();

                removedWatcher = new ManagementEventWatcher("SELECT * FROM __InstanceDeletionEvent WITHIN 5 WHERE TargetInstance ISA \"Win32_USBControllerDevice\"");
                removedWatcher.EventArrived += new EventArrivedEventHandler(HandleRemovedEvent);
                removedWatcher.Start();
            }
            catch (ManagementException err)
            {
                ExceptionHelper.Manage("WMIEventWatcher:StartWatchUSB", err);
            }
        }

        /// <summary>
        /// stop watching for logical device events
        /// </summary>
        public void StopWatchUSB()
        {
            try
            {
                // Stop listening for events
                if (addedWatcher != null)
                    addedWatcher.Stop();

                if (removedWatcher != null)
                    removedWatcher.Stop();
            }
            catch (ManagementException err)
            {
                ExceptionHelper.Manage("WMIEventWatcher:StopWatchUSB", err);
            }
        }

        /// <summary>
        /// handle the add event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HandleAddedEvent(object sender, EventArrivedEventArgs e)
        {
            USBDiskInfo device = null;

            try
            {
                ManagementBaseObject targetInstance = e.NewEvent["TargetInstance"] as ManagementBaseObject;

                DebugPrint(targetInstance);

                // get the device name in the dependent property Dependent: extract the last part
                // \\FR-L25676\root\cimv2:Win32_PnPEntity.DeviceID="USBSTOR\\DISK&VEN_USB&PROD_FLASH_DISK&REV_1100\\AA04012700076941&0"
                string PNP_deviceID = Convert.ToString(targetInstance["Dependent"]).Split('=').Last().Replace("\"", "").Replace("\\", "");
                string device_name = Convert.ToString(targetInstance["Dependent"]).Split('\\').Last().Replace("\"", "");

                // query that device entity
                ObjectQuery query = new ObjectQuery(string.Format("Select * from Win32_PnPEntity Where DeviceID like \"%{0}%\"", device_name));

                // check if match usb removable disk
                using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
                {
                    ManagementObjectCollection entities = searcher.Get();

                    //first loop to check USBSTOR
                    foreach (var entity in entities)
                    {
                        string service = Convert.ToString(entity["Service"]);
                        
                        if (service == "USBSTOR")
                            device = new USBDiskInfo();
                    }

                    if (device != null)
                    {
                        foreach (var entity in entities)
                        {
                            string service = Convert.ToString(entity["Service"]);
                            if (service == "disk")
                            {
                                GetDiskInformation(device, device_name);

                                Devices.Add(device);
                                if (EventArrived != null)
                                    EventArrived(this, new WMIEventArgs() { Disk = device, EventType = WMIActions.Added });
                            }
                        }
                    }
                }
            }
            catch (ManagementException err)
            {
                ExceptionHelper.Manage("WMIEventWatcher:HandleAddedEvent", err);
            }
        }

        private ManagementObjectSearcher GetDiskInformation(USBDiskInfo device, string device_name)
        {
            ManagementObjectSearcher searcher2 = null;
                 
            ObjectQuery query1 = new ObjectQuery("SELECT * FROM Win32_DiskDrive where PNPDeviceID like '%" + device_name + "%'");
            searcher2 = new ManagementObjectSearcher(query1);

            ManagementObjectCollection disks = searcher2.Get();
            foreach (var disk in disks)
            {
                DebugPrint(disk);

                //Use the disk drive device id to find associated partition
                ObjectQuery query2 = new ObjectQuery("ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + Convert.ToString(disk["DeviceID"]).Replace("\"", "\\") + "'} WHERE AssocClass=Win32_DiskDriveToDiskPartition");
                searcher2 = new ManagementObjectSearcher(query2);

                ManagementObjectCollection partitions = searcher2.Get();
                foreach (var part in partitions)
                {
                    DebugPrint(part);

                    //Use partition device id to find logical disk
                    ObjectQuery query3 = new ObjectQuery("ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + Convert.ToString(part["DeviceID"]).Replace("\"", "\\") + "'} WHERE AssocClass=Win32_LogicalDiskToPartition");
                    searcher2 = new ManagementObjectSearcher(query3);

                    ManagementObjectCollection logic = searcher2.Get();
                    foreach (var disklogic in logic)
                    {
                        DebugPrint(disklogic);

                        ParseDiskDriveInfo(device, disk);
                        ParseDiskLogicalInfo(device, disklogic);
                    }
                }
            }
            return searcher2;
        }

        /// <summary>
        /// handle the remove event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HandleRemovedEvent(object sender, EventArrivedEventArgs e)
        {
            try
            {
                ManagementBaseObject targetInstance = e.NewEvent["TargetInstance"] as ManagementBaseObject;

                DebugPrint(targetInstance);

                string PNP_deviceID = Convert.ToString(targetInstance["Dependent"]).Split('=').Last().Replace("\"", "").Replace("\\", "");

                USBDiskInfo device = Devices.Find(x => x.PNPDeviceID == PNP_deviceID);
                if( device != null )
                {
                    Devices.Remove( device );
                    if (EventArrived != null)
                        EventArrived(this, new WMIEventArgs() { Disk = device, EventType = WMIActions.Removed });
                }
            }
            catch (ManagementException err)
            {
                ExceptionHelper.Manage("WMIEventWatcher:HandleRemovedEvent", err);
            }
        }

        /// <summary>
        /// when starting, get a list of all existing logical disk
        /// </summary>
        /// <returns></returns>
        private List<USBDiskInfo> GetExistingDevices()
        {
            try
            {
                List<USBDiskInfo> devices = new List<USBDiskInfo>();

                ObjectQuery diskQuery = new ObjectQuery("Select * from Win32_DiskDrive where InterfaceType='USB'");

                foreach (ManagementObject drive in new ManagementObjectSearcher(diskQuery).Get())
                {
                    ObjectQuery partQuery = new ObjectQuery( 
                        String.Format("associators of {{Win32_DiskDrive.DeviceID='{0}'}} where AssocClass = Win32_DiskDriveToDiskPartition", drive["DeviceID"])
                        );

                    DebugPrint(drive);

                    foreach (ManagementObject partition in new ManagementObjectSearcher(partQuery).Get())
                    {
                        // associate partitions with logical disks (drive letter volumes)
                        ObjectQuery logicalQuery = new ObjectQuery( 
                        String.Format("associators of {{Win32_DiskPartition.DeviceID='{0}'}} where AssocClass = Win32_LogicalDiskToPartition", partition["DeviceID"])
                        );

                        DebugPrint(partition);

                        foreach (ManagementObject logical in new ManagementObjectSearcher(logicalQuery).Get())
                        {
                            DebugPrint(logical);

                            USBDiskInfo disk = new USBDiskInfo();

                            ParseDiskDriveInfo(disk, drive);
                            ParseDiskLogicalInfo(disk, logical);

                            devices.Add(disk);
                        }
                    }
                }

                return devices;
            }
            catch (ManagementException err)
            {
                ExceptionHelper.Manage("WMIEventWatcher:GetDevices", err);
                return null;
            }
        }

        private void ParseDiskDriveInfo(USBDiskInfo disk, ManagementBaseObject drive)
        {
            disk.PNPDeviceID = drive["PNPDeviceID"].ToString().Replace("\\", "");
            disk.Model = drive["Model"].ToString();
            disk.Caption = drive["Caption"].ToString();
        }

        private void ParseDiskLogicalInfo(USBDiskInfo disk, ManagementBaseObject logical)
        {
            disk.Name = logical["Name"].ToString();
            disk.Path = logical["Name"].ToString();

            disk.VolumeName = logical["VolumeName"].ToString();
            disk.FreeSpace = (ulong)logical["FreeSpace"];
            disk.Size = (ulong)logical["Size"];
        }

        /// <summary>
        /// internal function to trace properties
        /// </summary>
        /// <param name="e"></param>
        private void DebugPrint(ManagementBaseObject e)
        {
            Console.WriteLine("--------------------------------------------------------------");
            Console.WriteLine("ClassPath : {0}", e.ClassPath);
            Console.WriteLine("Site : {0}", e.Site);

            foreach (PropertyData prop in e.Properties)
                Console.WriteLine("PROPERTY : {0} - {1}", prop.Name, prop.Value);

            foreach (PropertyData prop in e.SystemProperties)
                Console.WriteLine("SYSTEM : {0} - {1}", prop.Name, prop.Value);

            foreach (QualifierData prop in e.Qualifiers)
                Console.WriteLine("QUALIFIER : {0} - {1}", prop.Name, prop.Value);

            Console.WriteLine("--------------------------------------------------------------");
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Architect
France France
WPF and MVVM fan, I practice C # in all its forms from the beginning of the NET Framework without mentioning C ++ / MFC and other software packages such as databases, ASP, WCF, Web & Windows services, Application, and now Core and UWP.
In my wasted hours, I am guilty of having fathered C.B.R. and its cousins C.B.R. for WinRT and UWP on the Windows store.
But apart from that, I am a great handyman ... the house, a rocket stove to heat the jacuzzi and the last one: a wood oven for pizza, bread, and everything that goes inside

https://guillaumewaser.wordpress.com/
https://fouretcompagnie.wordpress.com/

Comments and Discussions