zoukankan      html  css  js  c++  java
  • C# USB Detection winform and WPF

    Win From Version:

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Management;
    using System.Runtime.InteropServices;


    namespace SyncContactDemo
    {
        
    class DriverWindow : NativeWindow, IDisposable
        {
            
    // Contains information about a logical volume.

            [StructLayout(LayoutKind.Sequential)]
            
    public struct DEV_BROADCAST_VOLUME
            {
                
    public int dbcv_size;            // size of the struct
                public int dbcv_devicetype;        // DBT_DEVTYP_VOLUME
                public int dbcv_reserved;        // reserved; do not use
                public int dbcv_unitmask;        // Bit 0=A, bit 1=B, and so on (bitmask)
                public short dbcv_flags;        // DBTF_MEDIA=0x01, DBTF_NET=0x02 (bitmask)
            }


            
    private const int WM_DEVICECHANGE = 0x0219;                // device state change
            private const int DBT_DEVICEARRIVAL = 0x8000;            // detected a new device
            private const int DBT_DEVICEQUERYREMOVE = 0x8001;        // preparing to remove
            private const int DBT_DEVICEREMOVECOMPLETE = 0x8004;    // removed 
            private const int DBT_DEVTYP_VOLUME = 0x00000002;        // logical volume


            
    public DriverWindow()
            {
                
    // create a generic window with no class name
                base.CreateHandle(new CreateParams());
            }


            
    public void Dispose()
            {
                
    base.DestroyHandle();
                GC.SuppressFinalize(
    this);
            }

            
    protected override void WndProc(ref Message message)
            {
                
    base.WndProc(ref message);

                
    if ((message.Msg == WM_DEVICECHANGE) && (message.LParam != IntPtr.Zero))
                {
                    
    switch (message.WParam.ToInt32())
                    {
                        
    case DBT_DEVICEARRIVAL:
                            SignalDeviceChange(UsbStateChange.Added);
                            
    break;

                        
    case DBT_DEVICEQUERYREMOVE:
                            
    // can intercept
                            break;

                        
    case DBT_DEVICEREMOVECOMPLETE:
                            SignalDeviceChange(UsbStateChange.Removed);
                            
    break;
                    }
                }
            }
            
    public event UsbStateChangedEventHandler StateChanged;

            
    private void SignalDeviceChange(UsbStateChange state)
            {

                
    if (StateChanged != null)
                {
                    StateChanged(
    new UsbStateChangedEventArgs(state));
                }
            }

        }
        
    public delegate void UsbStateChangedEventHandler(UsbStateChangedEventArgs e);
        
    public enum UsbStateChange
        {

            
    /// <summary>
            
    /// A device has been added and is now available.
            
    /// </summary>

            Added,


            
    /// <summary>
            
    /// A device is about to be removed;
            
    /// allows consumers to intercept and deny the action.
            
    /// </summary>

            Removing,


            
    /// <summary>
            
    /// A device has been removed and is no longer available.
            
    /// </summary>

            Removed
        }

        
    public class UsbStateChangedEventArgs : EventArgs
        {

            
    /// <summary>
            
    /// Initialize a new instance with the specified state and disk.
            
    /// </summary>
            
    /// <param name="state">The state change code.</param>
            
    /// <param name="disk">The USB disk description.</param>

            
    public UsbStateChangedEventArgs(UsbStateChange state)
            {
                
    this.State = state;
            }

            
    /// <summary>
            
    /// Gets the state change code.
            
    /// </summary>

            
    public UsbStateChange State
            {
                
    get;
                
    private set;
            }
        }
    }

    Override the WndProc(ref Message message) method is core code, which need winform support, so it can not be used in console application and WPF application.

    in the win from code, we can use it like 

     

      DriverWindow dw = new DriverWindow();
                dw.StateChanged 
    += new UsbStateChangedEventHandler(dw_StateChanged);

    The WPF version:

    代码
    using System.Runtime.InteropServices;
    using System;
    namespace Lenovo.Common.Devices
    {
        
    public class Win32
        {

            
    public const int DEVICE_NOTIFY_SERVICE_HANDLE = 1;
            
    public const int DEVICE_NOTIFY_WINDOW_HANDLE = 0;
            
    public const int DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 4;

            [Flags]
            
    public enum DEVICE_NOTIFY : uint
            {
                DEVICE_NOTIFY_WINDOW_HANDLE 
    = 0x00000000,
                DEVICE_NOTIFY_SERVICE_HANDLE 
    = 0x00000001,
                DEVICE_NOTIFY_ALL_INTERFACE_CLASSES 
    = 0x00000004
            }


            
    public const int SERVICE_CONTROL_STOP = 0x00000001;
            
    public const int SERVICE_CONTROL_DEVICEEVENT = 0x00000011;
            
    public const int SERVICE_CONTROL_SHUTDOWN = 0x00000005;
       
            
    /*DBT_DEVTYP_DEVICEINTERFACE 0x00000005
                Class of devices. This structure is a DEV_BROADCAST_DEVICEINTERFACE structure.
     
                DBT_DEVTYP_HANDLE   0x00000006
                File system handle. This structure is a DEV_BROADCAST_HANDLE structure.
     
                DBT_DEVTYP_OEM  0x00000000
                OEM- or IHV-defined device type. This structure is a DEV_BROADCAST_OEM structure.
     
                DBT_DEVTYP_PORT 0x00000003
                Port device (serial or parallel). This structure is a DEV_BROADCAST_PORT structure.
     
                DBT_DEVTYP_VOLUME 0x00000002
                Logical volume. This structure is a DEV_BROADCAST_VOLUME structure.
     
    */

            
    public const int DBT_DEVTYP_DEVICEINTERFACE = 0x00000005;
            
    public const int DBT_DEVTYP_HANDLE = 0x00000006;
            
    public const int DBT_DEVTYP_OEM = 0x00000000;
            
    public const int DBT_DEVTYP_PORT = 0x00000003;
            
    public const int DBT_DEVTYP_VOLUME = 0x00000002;


            
    public const int WM_DEVICECHANGE = 0x0219;                // device state change
            public const int DBT_DEVICEARRIVAL = 0x8000;            // detected a new device
            public const int DBT_DEVICEQUERYREMOVE = 0x8001;        // preparing to remove
            public const int DBT_DEVICEREMOVECOMPLETE = 0x8004;    // removed 
            public const int DBT_DEVNODES_CHANGED = 0x0007//A device has been added to or removed from the system.


            [DllImport(
    "user32.dll", SetLastError = true)]
            
    public static extern IntPtr RegisterDeviceNotification(IntPtr intPtr, IntPtr notificationFilter, uint flags);

            [DllImport(
    "user32.dll", CharSet = CharSet.Auto)]
            
    public static extern uint UnregisterDeviceNotification(IntPtr hHandle);

            [StructLayout(LayoutKind.Sequential, CharSet 
    = CharSet.Unicode)]
            
    public struct DEV_BROADCAST_DEVICEINTERFACE
            {
                
    public int dbcc_size;
                
    public int dbcc_devicetype;
                
    public int dbcc_reserved;
                
    //public IntPtr dbcc_handle;
                
    //public IntPtr dbcc_hdevnotify;
                [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 16)]
                
    public byte[] dbcc_classguid;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst 
    = 128)]
                
    public Char[] dbcc_name;
                
    //public byte dbcc_data;
                
    //public byte dbcc_data1; 
            
            }

            [StructLayout(LayoutKind.Sequential)]
            
    public struct DEV_BROADCAST_HDR
            {
                
    public int dbcc_size;
                
    public int dbcc_devicetype;
                
    public int dbcc_reserved;
            }

            [StructLayout(LayoutKind.Sequential)]
            
    public struct DEV_BROADCAST_HANDLE
            {
                
    public int dbch_size;
                
    public int dbch_devicetype;
                
    public int dbch_reserved;
                
    public IntPtr dbch_handle;
                
    public IntPtr dbch_hdevnotify;
                
    public Guid dbch_eventguid;
                
    public long dbch_nameoffset;
                
    public Byte dbch_data;
                
    public Byte dbch_data1;
            }
        }
    }
    代码
    using System.Runtime.InteropServices;
    using System;

    namespace Lenovo.Common.Devices
    {
        
    public delegate void UsbStateChangedEventHandler(bool arrival);
        
    public class UsbDetector
        {
            
    public enum WM_DEVICECHANGE_WPPARAMS
            {
                DBT_DEVICEARRIVAL 
    = 0x8000,
                DBT_DEVICEQUERYREMOVE 
    = 0x8001,
                DBT_DEVICEREMOVECOMPLETE 
    = 0x8004,
                DBT_CONFIGCHANGECANCELED 
    = 0x19,
                DBT_CONFIGCHANGED 
    = 0x18,
                DBT_CUSTOMEVENT 
    = 0x8006,
                DBT_DEVICEQUERYREMOVEFAILED 
    = 0x8002,
                DBT_DEVICEREMOVEPENDING 
    = 0x8003,
                DBT_DEVICETYPESPECIFIC 
    = 0x8005,
                DBT_DEVNODES_CHANGED 
    = 0x7,
                DBT_QUERYCHANGECONFIG 
    = 0x17,
                DBT_USERDEFINED 
    = 0xFFFF
            }
            
    const int WM_DEVICECHANGE = 0x0219;

            
    public IntPtr HwndHandler(IntPtr hwnd, int msg, IntPtr wParam, IntPtr LParam, ref bool handled)
            {
                ProcessWinMessage(msg, wParam, LParam);
              
    //  handled = false;
                return IntPtr.Zero;
            }

            
    public event UsbStateChangedEventHandler StateChanged;

            
    public void ProcessWinMessage(int msg, IntPtr wParam, IntPtr LParam)
            {
              
    //  if ((msg == WM_DEVICECHANGE) && (LParam != IntPtr.Zero))
                if (msg == WM_DEVICECHANGE) 
                {
                    
    switch (wParam.ToInt32())
                    {
                        
    case Win32.DBT_DEVICEARRIVAL:
                            
    if (StateChanged != null)
                            {
                                StateChanged(
    true);
                            }
                            
    break;
                        
    case Win32.DBT_DEVICEREMOVECOMPLETE:
                            
    if (StateChanged != null)
                            {
                                StateChanged(
    false);
                            }
                            
    break;
                        
    case Win32.DBT_DEVNODES_CHANGED:
                            
    if (StateChanged != null)
                            {
                                StateChanged(
    false);
                            }
                            
    break;
                        
    default:
                            
    break;
                    }

                }
            }

           
    // private const string USBClassID = "c671678c-82c1-43f3-d700-0049433e9a4b";
            
    //http://msdn.microsoft.com/en-us/library/ff545972.aspx
            private const string USBClassID = "A5DCBF10-6530-11D2-901F-00C04FB951ED";
            
    public IntPtr RegisterDeviceNotification(IntPtr hwnd)
            {
                Win32.DEV_BROADCAST_DEVICEINTERFACE deviceInterface 
    = new Win32.DEV_BROADCAST_DEVICEINTERFACE();
                
    int size = Marshal.SizeOf(deviceInterface);
                deviceInterface.dbcc_size 
    = size;
            
    //    deviceInterface.dbcc_devicetype = Win32.DBT_DEVTYP_VOLUME;
                deviceInterface.dbcc_reserved = 0;
                
    //deviceInterface.dbcc_handle = hwnd;
                
    //deviceInterface.dbcc_hdevnotify = (IntPtr)0;
                deviceInterface.dbcc_classguid = new Guid(USBClassID).ToByteArray();
                IntPtr buffer 
    = IntPtr.Zero;
                buffer 
    = Marshal.AllocHGlobal(size);
                Marshal.StructureToPtr(deviceInterface, buffer, 
    true);
                IntPtr r 
    = IntPtr.Zero;
                r 
    = Win32.RegisterDeviceNotification(hwnd, buffer, 
                    (Int32)(Win32.DEVICE_NOTIFY.DEVICE_NOTIFY_ALL_INTERFACE_CLASSES  
                            
    | Win32.DEVICE_NOTIFY.DEVICE_NOTIFY_SERVICE_HANDLE | 
                            Win32.DEVICE_NOTIFY.DEVICE_NOTIFY_WINDOW_HANDLE)
                    );
                
                
    return r;
            }
        }
    }


     In the WPF application, we should register the DeviceNotification after the window is ready, so we should put them in the load event,

    in the constructor:

    代码
      UsbDetector usbDetector;
            
    public MainWindow()
            {
                InitializeComponent();
                usbDetector 
    = new UsbDetector();
                usbDetector.StateChanged 
    += new Lenovo.Common.Devices.UsbStateChangedEventHandler(usbDetector_StateChanged);

                
    this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
               
            }
      
    void MainWindow_Loaded(object sender, RoutedEventArgs e)
            {
                WindowInteropHelper interop 
    = new WindowInteropHelper(this);
                HwndSource hwndSource 
    = HwndSource.FromHwnd(interop.Handle);
                HwndSourceHook hool 
    = new HwndSourceHook(usbDetector.HwndHandler);
                hwndSource.AddHook(hool); ;
                usbDetector.RegisterDeviceNotification(interop.Handle);
            }

     
    void usbDetector_StateChanged(bool arrival)
            {
                
    if (arrival)
                    MessageBox.Show(
    "add");
                
    else
                    MessageBox.Show(
    "removed");
            }

    In generally, the wParam should be DBT_DEVICEARRIVAL or DBT_DEVICEREMOVECOMPLETE, but some time , it keep be the wParam =7 (DBT_DEVNODES_CHANGED) and LParam = 0, that is that the usb driver isn't correctly installed.

  • 相关阅读:
    e-icon-picker 基于element-ui图标和fontawesome图标选择器组件
    js 前端将平级数据转为树形数据的方法
    发送邮件报User does not have send-as privilege for错误的解决办法
    Dynamics 365利用email实体的DeliverIncomingEmail来做抓取邮件的进一步处理
    Dynamics 365中邮件模板的使用
    导入解决方案报错:Unable to retrieve customActivityInfo using RetrieveCustomActivityInfoWithSandboxPlugin
    Dynamics 365组织服务使用Query Expression查询数据时候请谨慎使用ConditionOperator.Contains
    【代码审计】ESPCMSP8(易思企业建站管理系统)漏洞报告
    MS16-072域内中间人攻击
    域控权限提升PTH攻击
  • 原文地址:https://www.cnblogs.com/skyfei/p/1914821.html
Copyright © 2011-2022 走看看