• U盘 USB 盘 拔插监测


    
    namespace ConsoleApplication
    {
        using System;
        using Microshaoft;
        public class Class1
        {
            static void Main(string[] args)
            {
                DriveDetector x = new DriveDetector();
                x.DeviceArrived += new DriveDetector.DriveDetectorEventHandler(x_DeviceArrived);
                x.DeviceRemoved += new DriveDetector.DriveDetectorEventHandler(x_DeviceRemoved);
                Console.WriteLine("Hello World");
                Console.WriteLine(Environment.Version.ToString());
                Console.ReadLine();
            }
            static void x_DeviceRemoved(DriveDetector sender, DriveDetectorEventArgs e)
            {
                Console.WriteLine("DeviceRemoved {0}", e.Drive);
            }
            static void x_DeviceArrived(DriveDetector sender, DriveDetectorEventArgs e)
            {
                Console.WriteLine("DeviceArrived {0}", e.Drive);
            }
        }
    }
    namespace Microshaoft
    {
        using System;
        using System.Windows.Forms;                // required for Message
        using System.Runtime.InteropServices;    // required for Marshal
        using System.IO;
        using Microsoft.Win32.SafeHandles;
        using System.Threading;
        public class DriveDetectorEventArgs : EventArgs
        {
            public DriveDetectorEventArgs()
            {
                Cancel = false;
                Drive = "";
                HookQueryRemove = false;
            }
            public bool Cancel;
            public string Drive;
            public bool HookQueryRemove;
        }
        public class DriveDetector : IDisposable
        {
            public event DriveDetectorEventHandler DeviceArrived;
            public event DriveDetectorEventHandler DeviceRemoved;
            public event DriveDetectorEventHandler QueryRemove;
            public delegate void DriveDetectorEventHandler(DriveDetector sender, DriveDetectorEventArgs e);
            private WindowsMessagesListener _listener;// = new WindowsMessagesListener();
            private IntPtr _DirHandle = IntPtr.Zero;
            private FileStream _FileOnFlash = null;
            private string _FileToOpen;
            private IntPtr _DeviceNotifyHandle;
            private IntPtr _hWnd;
            private string _CurrentDrive;
            private Thread _thread;
            private class WindowsMessagesListener : Form//NativeWindow
            {
                public delegate void WndProcEventHandler(ref Message m, bool cancel);
                public event WndProcEventHandler BeforeBaseWndProc;
                public event WndProcEventHandler AfterBaseWndProc;
                protected override void WndProc(ref Message m)
                {
                    bool b = false;
                    if (BeforeBaseWndProc != null)
                    {
                        BeforeBaseWndProc(ref m, b);
                    }
                    if (!b)
                    {
                        base.WndProc(ref m);
                        if (AfterBaseWndProc != null)
                        {
                            AfterBaseWndProc(ref m, b);
                        }
                    }
                }
            }
            public DriveDetector()
            {
                Init(null);
            }
            public DriveDetector(string FileToOpen)
            {
                Init(FileToOpen);
            }
            private void Init(string fileToOpen)
            {
                _thread = new Thread(new ThreadStart(Run)); //监视线程: 显示滚动计数器
                _thread.Start();
                _FileToOpen = fileToOpen;
                _FileOnFlash = null;
                _DeviceNotifyHandle = IntPtr.Zero;
                _DirHandle = IntPtr.Zero;   // handle to the root directory of the flash drive which we open 
                _CurrentDrive = "";
            }
            private void Run()
            {
                _listener = new WindowsMessagesListener();
                _hWnd = _listener.Handle;
                _listener.AfterBaseWndProc += new WindowsMessagesListener.WndProcEventHandler(_listener_AfterBaseWndProc);
                Application.Run();
            }
            void _listener_AfterBaseWndProc(ref Message m, bool canceledBaseWndProc)
            {
                int devType;
                char c;
                if (m.Msg == Win32Native.WM_DEVICECHANGE)
                {
                    // WM_DEVICECHANGE can have several meanings depending on the WParam value...
                    switch (m.WParam.ToInt32())
                    {
                        //
                        // New device has just arrived
                        //
                        case Win32Native.DBT_DEVICEARRIVAL :
                            devType = Marshal.ReadInt32(m.LParam, 4);
                            if (devType == Win32Native.DBT_DEVTYP_VOLUME)
                            {
                                DEV_BROADCAST_VOLUME vol;
                                vol = (DEV_BROADCAST_VOLUME)
                                    Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));
                                // Get the drive letter 
                                c = DriveMaskToLetter(vol.dbcv_unitmask);
                                //
                                // Call the client event handler
                                //
                                // We should create copy of the event before testing it and
                                // calling the delegate - if any
                                DriveDetectorEventHandler tempDeviceArrived = DeviceArrived;
                                if (tempDeviceArrived != null)
                                {
                                    DriveDetectorEventArgs e = new DriveDetectorEventArgs();
                                    e.Drive = c + ":\\";
                                    tempDeviceArrived(this, e);
                                    // Register for query remove if requested
                                    if (e.HookQueryRemove)
                                    {
                                        // If something is already hooked, unhook it now
                                        if (_DeviceNotifyHandle != IntPtr.Zero)
                                        {
                                            RegisterForDeviceChange(false, null);
                                        }
                                        RegisterQuery(c + ":\\");
                                    }
                                }    // if  has event handler
                            }
                            break;
                        //
                        // Device is about to be removed
                        // Any application can cancel the removal
                        //
                        case Win32Native.DBT_DEVICEQUERYREMOVE :
                            devType = Marshal.ReadInt32(m.LParam, 4);
                            if (devType == Win32Native.DBT_DEVTYP_HANDLE)
                            {
                                // TODO: we could get the handle for which this message is sent 
                                // from vol.dbch_handle and compare it against a list of handles for 
                                // which we have registered the query remove message (?)                                                
                                //DEV_BROADCAST_HANDLE vol;
                                //vol = (DEV_BROADCAST_HANDLE)
                                //   Marshal.PtrToStructure(_.LParam, typeof(DEV_BROADCAST_HANDLE));
                                // if ( vol.dbch_handle ....
                                //
                                // Call the event handler in client
                                //
                                DriveDetectorEventHandler tempQuery = QueryRemove;
                                if (tempQuery != null)
                                {
                                    DriveDetectorEventArgs e = new DriveDetectorEventArgs();
                                    e.Drive = _CurrentDrive;        // drive which is hooked
                                    tempQuery(this, e);
                                    // If the client wants to cancel, let Windows know
                                    if (e.Cancel)
                                    {
                                        m.Result = (IntPtr)Win32Native.BROADCAST_QUERY_DENY;
                                    }
                                    else
                                    {
                                        // Change 28.10.2007: Unregister the notification, this will
                                        // close the handle to file or root directory also. 
                                        // We have to close it anyway to allow the removal so
                                        // even if some other app cancels the removal we would not know about it...
                                        RegisterForDeviceChange(false, null);   // will also close the mFileOnFlash
                                    }
                                }
                            }
                            break;
                        //
                        // Device has been removed
                        //
                        case Win32Native.DBT_DEVICEREMOVECOMPLETE :
                            devType = Marshal.ReadInt32(m.LParam, 4);
                            if (devType == Win32Native.DBT_DEVTYP_VOLUME)
                            {
                                devType = Marshal.ReadInt32(m.LParam, 4);
                                if (devType == Win32Native.DBT_DEVTYP_VOLUME)
                                {
                                    DEV_BROADCAST_VOLUME vol;
                                    vol = (DEV_BROADCAST_VOLUME)
                                        Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));
                                    c = DriveMaskToLetter(vol.dbcv_unitmask);
                                    //
                                    // Call the client event handler
                                    //
                                    DriveDetectorEventHandler tempDeviceRemoved = DeviceRemoved;
                                    if (tempDeviceRemoved != null)
                                    {
                                        DriveDetectorEventArgs e = new DriveDetectorEventArgs();
                                        e.Drive = c + ":\\";
                                        tempDeviceRemoved(this, e);
                                    }
                                    // TODO: we could unregister the notify handle here if we knew it is the
                                    // right drive which has been just removed
                                    //RegisterForDeviceChange(false, null);
                                }
                            }
                            break;
                    }
                }
            }
            public bool IsQueryHooked
            {
                get
                {
                    if (_DeviceNotifyHandle == IntPtr.Zero)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
            }
            public string HookedDrive
            {
                get
                {
                    return _CurrentDrive;
                }
            }
            public FileStream OpenedFile
            {
                get
                {
                    return _FileOnFlash;
                }
            }
            public bool EnableQueryRemove(string fileOnDrive)
            {
                if (fileOnDrive == null || fileOnDrive.Length == 0)
                {
                    throw new ArgumentException("Drive path must be supplied to register for Query remove.");
                }
                if (fileOnDrive.Length == 2 && fileOnDrive[1] == ':')
                {
                    fileOnDrive += '\\';        // append "\\" if only drive letter with ":" was passed in.
                }
                if (_DeviceNotifyHandle != IntPtr.Zero)
                {
                    // Unregister first...
                    RegisterForDeviceChange(false, null);
                }
                if (Path.GetFileName(fileOnDrive).Length == 0 || !File.Exists(fileOnDrive))
                {
                    _FileToOpen = null;    // use root directory...
                }
                else
                {
                    _FileToOpen = fileOnDrive;
                }
                RegisterQuery(Path.GetPathRoot(fileOnDrive));
                if (_DeviceNotifyHandle == IntPtr.Zero)
                {
                    return false;   // failed to register
                }
                return true;
            }
            public void DisableQueryRemove()
            {
                if (_DeviceNotifyHandle != IntPtr.Zero)
                {
                    RegisterForDeviceChange(false, null);
                }
            }
            public void Dispose()
            {
                RegisterForDeviceChange(false, null);
            }
            private void RegisterQuery(string drive)
            {
                bool register = true;
                if (!String.IsNullOrEmpty(_FileToOpen))
                {
                    // Make sure the path in mFileToOpen contains valid drive
                    // If there is a drive letter in the path, it may be different from the  actual
                    // letter assigned to the drive now. We will cut it off and merge the actual drive 
                    // with the rest of the path.
                    if (_FileToOpen.Contains(":"))
                    {
                        string tmp = _FileToOpen.Substring(3);
                        string root = Path.GetPathRoot(drive);
                        _FileToOpen = Path.Combine(root, tmp);
                    }
                    else
                    {
                        _FileToOpen = Path.Combine(drive, _FileToOpen);
                    }
                }
                try
                {
                    //mFileOnFlash = new FileStream(_FileToOpen, FileMode.Open);
                    // Change 28.10.2007 - Open the root directory 
                    if (_FileToOpen == null)  // open root directory
                    {
                        _FileOnFlash = null;
                    }
                    else
                    {
                        _FileOnFlash = new FileStream(_FileToOpen, FileMode.Open);
                    }
                }
                catch (Exception)
                {
                    // just do not register if the file could not be opened
                    register = false;
                }
                if (register)
                {
                    //RegisterForDeviceChange(true, mFileOnFlash.SafeFileHandle);
                    //mCurrentDrive = drive;
                    // Change 28.10.2007 - Open the root directory 
                    if (_FileOnFlash == null)
                    {
                        RegisterForDeviceChange(drive);
                    }
                    else
                    {
                        // old version
                        RegisterForDeviceChange(true,_FileOnFlash.SafeFileHandle);
                    }
                    _CurrentDrive = drive;
                }
            }
            private void RegisterForDeviceChange(string dirPath)
            {
                IntPtr handle = Win32Native.OpenDirectory(dirPath);
                if (handle == IntPtr.Zero)
                {
                    _DeviceNotifyHandle = IntPtr.Zero;
                    return;
                }
                else
                    _DirHandle = handle;    // save handle for closing it when unregistering
                // Register for handle
                DEV_BROADCAST_HANDLE data = new DEV_BROADCAST_HANDLE();
                data.dbch_devicetype = Win32Native.DBT_DEVTYP_HANDLE;
                data.dbch_reserved = 0;
                data.dbch_nameoffset = 0;
                //data.dbch_data = null;
                //data.dbch_eventguid = 0;
                data.dbch_handle = handle;
                data.dbch_hdevnotify = (IntPtr)0;
                int size = Marshal.SizeOf(data);
                data.dbch_size = size;
                IntPtr buffer = Marshal.AllocHGlobal(size);
                Marshal.StructureToPtr(data, buffer, true);
                _DeviceNotifyHandle = Win32Native.RegisterDeviceNotification(_hWnd, buffer, 0);
            }
            private void RegisterForDeviceChange(bool register, SafeFileHandle fileHandle)
            {
                if (register)
                {
                    // Register for handle
                    DEV_BROADCAST_HANDLE data = new DEV_BROADCAST_HANDLE();
                    data.dbch_devicetype = Win32Native.DBT_DEVTYP_HANDLE;
                    data.dbch_reserved = 0;
                    data.dbch_nameoffset = 0;
                    //data.dbch_data = null;
                    //data.dbch_eventguid = 0;
                    data.dbch_handle = fileHandle.DangerousGetHandle(); //Marshal. fileHandle; 
                    data.dbch_hdevnotify = (IntPtr)0;
                    int size = Marshal.SizeOf(data);
                    data.dbch_size = size;
                    IntPtr buffer = Marshal.AllocHGlobal(size);
                    Marshal.StructureToPtr(data, buffer, true);
                    _DeviceNotifyHandle = Win32Native.RegisterDeviceNotification(_hWnd, buffer, 0);
                }
                else
                {
                    // close the directory handle
                    if (_DirHandle != IntPtr.Zero)
                    {
                        Win32Native.CloseDirectoryHandle(_DirHandle);
                        //    string er = Marshal.GetLastWin32Error().ToString();
                    }
                    // unregister
                    if (_DeviceNotifyHandle != IntPtr.Zero)
                    {
                        Win32Native.UnregisterDeviceNotification(_DeviceNotifyHandle);
                    }
                    _DeviceNotifyHandle = IntPtr.Zero;
                    _DirHandle = IntPtr.Zero;
                    _CurrentDrive = "";
                    if (_FileOnFlash != null)
                    {
                        _FileOnFlash.Close();
                        _FileOnFlash = null;
                    }
                }
            }
            private static char DriveMaskToLetter(int mask)
            {
                char c;
                string drives = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                // 1 = A
                // 2 = B
                // 4 = C...
                int i = 0;
                int p = mask / 2;
                while (p != 0)
                {
                    p = p / 2;
                    i ++;
                }
                if (i < drives.Length)
                {
                    c = drives[i];
                }
                else
                {
                    c = '?';
                }
                return c;
            }
            private class Win32Native
            {
                // Win32 constants
                public const int DBT_DEVTYP_DEVICEINTERFACE = 5;
                public const int DBT_DEVTYP_HANDLE = 6;
                public const int BROADCAST_QUERY_DENY = 0x424D5144;
                public const int WM_DEVICECHANGE = 0x0219;
                public const int DBT_DEVICEARRIVAL = 0x8000; // system detected a new device
                public const int DBT_DEVICEQUERYREMOVE = 0x8001;   // Preparing to remove (any program can disable the removal)
                public const int DBT_DEVICEREMOVECOMPLETE = 0x8004; // removed 
                public const int DBT_DEVTYP_VOLUME = 0x00000002; // drive type is logical volume
                //   HDEVNOTIFY RegisterDeviceNotification(HANDLE hRecipient,LPVOID NotificationFilter,DWORD Flags);
                [DllImport("user32.dll", CharSet = CharSet.Auto)]
                public static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, uint Flags);
                [DllImport("user32.dll", CharSet = CharSet.Auto)]
                public static extern uint UnregisterDeviceNotification(IntPtr hHandle);
                //
                // CreateFile  - MSDN
                const uint GENERIC_READ = 0x80000000;
                const uint OPEN_EXISTING = 3;
                const uint FILE_SHARE_READ = 0x00000001;
                const uint FILE_SHARE_WRITE = 0x00000002;
                const uint FILE_ATTRIBUTE_NORMAL = 128;
                const uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
                static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
                // should be "static extern unsafe"
                [DllImport("kernel32", SetLastError = true)]
                static extern IntPtr CreateFile
                                            (
                                                string FileName,                    // file name
                                                uint DesiredAccess,                // access mode
                                                uint ShareMode,                    // share mode
                                                uint SecurityAttributes,            // Security Attributes
                                                uint CreationDisposition,          // how to create
                                                uint FlagsAndAttributes,            // file attributes
                                                int hTemplateFile                  // handle to template file
                                            );
                [DllImport("kernel32", SetLastError = true)]
                static extern bool CloseHandle
                                            (
                                                IntPtr hObject   // handle to object
                                            );
                static public IntPtr OpenDirectory(string dirPath)
                {
                    // open the existing file for reading         
                    IntPtr handle = CreateFile
                                            (
                                                dirPath,
                                                GENERIC_READ,
                                                FILE_SHARE_READ | FILE_SHARE_WRITE,
                                                0,
                                                OPEN_EXISTING,
                                                FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL,
                                                0
                                            );
                    if (handle == INVALID_HANDLE_VALUE)
                    {
                        return IntPtr.Zero;
                    }
                    else
                    {
                        return handle;
                    }
                }
                public static bool CloseDirectoryHandle(IntPtr handle)
                {
                    return CloseHandle(handle);
                }
            }
            // Structure with information for RegisterDeviceNotification.
            [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[1]; // = new byte[1];
                public byte dbch_data;
                public byte dbch_data1;
            }
            // Struct for parameters of the WM_DEVICECHANGE message
            [StructLayout(LayoutKind.Sequential)]
            public struct DEV_BROADCAST_VOLUME
            {
                public int dbcv_size;
                public int dbcv_devicetype;
                public int dbcv_reserved;
                public int dbcv_unitmask;
            }
        }
    }
    
    
  • 相关阅读:
    famous javascript library.
    54陈上有一些技术文章
    codeforces 612A The Text Splitting(扩展欧几里得)
    UVA 11235 Frequent values
    codeforces 604A Uncowed Forces
    nyoj 138 找球号(二)
    codeforces 592A PawnChess
    cidefirces Educational Codeforces Round 2 A. Extract Numbers
    cidefirces Educational Codeforces Round 2 B Queries about less or equal elements
    codeforces Educational Codeforces Round 2 C Make Palindrome
  • 原文地址:https://www.cnblogs.com/Microshaoft/p/1363850.html
Copyright © 2020-2023  润新知