对于文件系统观察程序,使用DBT_DEVICEQUERYREMOVE事件类型的Usb弹出不起作用

时间:2017-02-21 14:21:40

标签: c# .net dllimport

我创建了一个服务并运行了USb已连接的代码,并且eventType为" DBT_DEVICEARRIVAL"当我们"弹出Usb"并且eventType是" DBT_DEVICEQUERYREMOVE"被击中但安全移除不起作用。

将消息显示为

  

"此设备目前正在使用中。关闭任何程序或窗口   可能正在使用该设备,然后再试一次"

我的代码是:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;
using System.Threading;

namespace UsbService
{
    public partial class EntredaUsbService : ServiceBase
    {
        public static string log_path = AppDomain.CurrentDomain.BaseDirectory.ToString() + "\\Usbservice.log";
        static string deviceid = "";
        static string path = "";
        static long oldstamp;
        static long oldstamp1;
        static string create;
        public static long usbval = 0;
        public static string drivecaption = "";
        public static long setdrive = 0;
        private IntPtr deviceNotifyHandle;
        private IntPtr deviceEventHandle;
        private IntPtr directoryHandle;
        public static int prev_control = 0;
        public static int prev_eventtype = 0;
        private Win32.ServiceControlHandlerEx myCallback;

        private int ServiceControlHandler(int control, int eventType, IntPtr eventData, IntPtr context)
        {
            File.AppendAllText(log_path, "Entered into ServiceControlHandler" + Environment.NewLine);
            File.AppendAllText(log_path, "Control is : " + control + "event type is :" + eventType + "event data is :" + eventData + "context is : " + context + Environment.NewLine);

            while (eventType != prev_eventtype)
            {
                prev_eventtype = eventType;
                prev_control = control;
                if (control == Win32.SERVICE_CONTROL_STOP || control == Win32.SERVICE_CONTROL_SHUTDOWN)
                {
                    UnregisterHandles();
                    Win32.UnregisterDeviceNotification(deviceEventHandle);
                    File.AppendAllText(log_path, "Stopping or shutdown the service" + Environment.NewLine);
                    base.Stop();
                }
                else if (control == Win32.SERVICE_CONTROL_DEVICEEVENT)
                {
                    FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
                    File.AppendAllText(log_path, "Control is : " + control + "event type is before switch :" + eventType);

                    switch (eventType)
                    {
                        case Win32.DBT_DEVICEQUERYREMOVE:
                            File.AppendAllText(log_path, "Eventtype is DBT_DEVICEQUERYREMOVE" + Environment.NewLine);
                            fileSystemWatcher.EnableRaisingEvents = false;
                            //  fileSystemWatcher.Dispose();
                            UnregisterHandles();
                            File.AppendAllText(log_path, "fswatcher raising events are :" + fileSystemWatcher.EnableRaisingEvents + Environment.NewLine);
                            break;

                        case Win32.DBT_DEVICEREMOVECOMPLETE:
                            File.AppendAllText(log_path, "Eventtype is DBT_DEVICEREMOVECOMPLETE" + Environment.NewLine);
                            break;

                        case Win32.DBT_DEVICEARRIVAL:
                            string driveLetter = "";
                            File.AppendAllText(log_path, "Entered into DBT_DEVICEARRIVAL" + Environment.NewLine);
                            Win32.DEV_BROADCAST_HDR hdr;
                            hdr = (Win32.DEV_BROADCAST_HDR)
                                Marshal.PtrToStructure(eventData, typeof(Win32.DEV_BROADCAST_HDR));

                            if (hdr.dbcc_devicetype == Win32.DBT_DEVTYP_DEVICEINTERFACE)
                            {
                                File.AppendAllText(log_path, "Hdr.dbcc_devicetype is :" + hdr.dbcc_devicetype + Environment.NewLine);
                                Win32.DEV_BROADCAST_DEVICEINTERFACE deviceInterface;
                                deviceInterface = (Win32.DEV_BROADCAST_DEVICEINTERFACE)
                                    Marshal.PtrToStructure(eventData, typeof(Win32.DEV_BROADCAST_DEVICEINTERFACE));
                                var usbdrives = DriveInfo.GetDrives();
                                foreach (var usbdrive in usbdrives)
                                {
                                    if (usbdrive.DriveType == DriveType.Removable)
                                    {
                                        //   string drivepah = usbdrive.Name;
                                        driveLetter = usbdrive.Name;
                                        File.AppendAllText(log_path, "Drive letter is : " + driveLetter + Environment.NewLine);
                                    }
                                }
                                /*
                                if (!Win32.GetVolumePathNamesForVolumeNameW(stringBuilder.ToString(), driveLetter, stringReturnLength, ref stringReturnLength))
                                {
                                    File.AppendAllText(log_path, "getvolume is null" + Environment.NewLine);
                                }
                                */
                                RegisterForHandle(driveLetter[0]);
                                //  usbdrives = DriveInfo.GetDrives();
                                //   foreach (var usbdrive in usbdrives)
                                {
                                    //  if (usbdrive.DriveType == DriveType.Removable)
                                    {

                                        //  File.AppendAllText(log_path, "USBDrive:" + usbdrive.Name);
                                        //    string drivepath = usbdrive.Name;
                                        fileSystemWatcher.Path = driveLetter;
                                        File.AppendAllText(log_path, "Drive path is :" + driveLetter + Environment.NewLine);
                                        fileSystemWatcher.NotifyFilter = NotifyFilters.Size | NotifyFilters.FileName | NotifyFilters.DirectoryName;
                                        fileSystemWatcher.IncludeSubdirectories = true;
                                        fileSystemWatcher.Filter = "*.*";
                                        fileSystemWatcher.InternalBufferSize = 1321440;
                                        fileSystemWatcher.Created += new System.IO.FileSystemEventHandler(fileSystemWatcher_Created);
                                        fileSystemWatcher.Deleted += new System.IO.FileSystemEventHandler(fileSystemWatcher_Deleted);
                                        fileSystemWatcher.Changed += new System.IO.FileSystemEventHandler(fileSystemWatcher_Changed);
                                        fileSystemWatcher.Renamed += new System.IO.RenamedEventHandler(fileSystemWatcher_Renamed);
                                        fileSystemWatcher.EnableRaisingEvents = true;
                                        File.AppendAllText(log_path, "fswatcher raising events are: " + fileSystemWatcher.EnableRaisingEvents + Environment.NewLine);
                                    }
                                }
                            }
                            break;
                    }
                }

            }
            return 0;
        }
        private void UnregisterHandles()
        {
            File.AppendAllText(log_path, "Entered into UnregisterHandles" + Environment.NewLine);
            File.AppendAllText(log_path, "directory handle : " + directoryHandle + " devicenotifyhandle : " + deviceNotifyHandle + Environment.NewLine);
            if (directoryHandle != IntPtr.Zero)
            {
                bool k = Win32.CloseHandle(directoryHandle);
                File.AppendAllText(log_path, "Close handle return : " + k + Environment.NewLine);
                directoryHandle = IntPtr.Zero;
            }
            if (deviceNotifyHandle != IntPtr.Zero)
            {
               uint k =  Win32.UnregisterDeviceNotification(deviceNotifyHandle);
               File.AppendAllText(log_path, "UnregisterDeviceNotification return : " + k + Environment.NewLine);
                deviceNotifyHandle = IntPtr.Zero;
            }
        }

        private void RegisterForHandle(char c)
        {
            File.AppendAllText(log_path, "Register to handle and char c is :" + c + Environment.NewLine);
            Win32.DEV_BROADCAST_HANDLE deviceHandle = new Win32.DEV_BROADCAST_HANDLE();
            File.AppendAllText(log_path, "Device handle is : " + deviceHandle + Environment.NewLine);
            int size = Marshal.SizeOf(deviceHandle);
            deviceHandle.dbch_size = size;
            deviceHandle.dbch_devicetype = Win32.DBT_DEVTYP_HANDLE;
            directoryHandle = CreateFileHandle(c + ":\\");
            File.AppendAllText(log_path, "Directory handle : " + directoryHandle + Environment.NewLine);
            deviceHandle.dbch_handle = directoryHandle;
            IntPtr buffer = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(deviceHandle, buffer, true);
            deviceNotifyHandle = Win32.RegisterDeviceNotification(this.ServiceHandle, buffer, Win32.DEVICE_NOTIFY_SERVICE_HANDLE);
            if (deviceNotifyHandle == IntPtr.Zero)
            {
                File.AppendAllText(log_path, "DeviceNotifyhandle is null" + Environment.NewLine);
            }
            else
            {
                File.AppendAllText(log_path, "DeviceNotifyHandle is : " + deviceNotifyHandle + Environment.NewLine);
            }
        }

        private void RegisterDeviceNotification(string logpath)
        {
            File.AppendAllText(logpath, "Entered into RegisterDeviceNotification" + Environment.NewLine);
           // while (true)
            {
                myCallback = new Win32.ServiceControlHandlerEx(ServiceControlHandler);
               IntPtr m =  Win32.RegisterServiceCtrlHandlerEx(this.ServiceName, myCallback, IntPtr.Zero);
               File.AppendAllText(logpath, "Register m value : " + m + Environment.NewLine);
            }

            if (this.ServiceHandle == IntPtr.Zero)
            {
                File.AppendAllText(logpath, "Service Handle is null" + Environment.NewLine);
            }
            else
            {
                File.AppendAllText(logpath, "Service handle is :" + this.ServiceHandle + Environment.NewLine);
            }

            Win32.DEV_BROADCAST_DEVICEINTERFACE deviceInterface = new Win32.DEV_BROADCAST_DEVICEINTERFACE();
            File.AppendAllText(logpath, "Device Interface is :" + deviceInterface + Environment.NewLine);
            int size = Marshal.SizeOf(deviceInterface);
            deviceInterface.dbcc_size = size;
            deviceInterface.dbcc_devicetype = Win32.DBT_DEVTYP_DEVICEINTERFACE;
            IntPtr buffer = default(IntPtr);
            buffer = Marshal.AllocHGlobal(size);

            Marshal.StructureToPtr(deviceInterface, buffer, true);
            deviceEventHandle = Win32.RegisterDeviceNotification(this.ServiceHandle, buffer, Win32.DEVICE_NOTIFY_SERVICE_HANDLE | Win32.DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
            if (deviceEventHandle == IntPtr.Zero)
            {
                File.AppendAllText(logpath, "DeviceEventHandle is null" + Environment.NewLine);
            }
            else
            {
                File.AppendAllText(logpath, "DeviceEventHandle is : " + deviceEventHandle + Environment.NewLine);
            }
        }


        public EntredaUsbService()
        {
            InitializeComponent();
        }
        void fileSystemWatcher_Created(object sender, System.IO.FileSystemEventArgs e)
        {
            File.AppendAllText(log_path, "Entered into fswatcher_created" + Environment.NewLine);
        }

        void fileSystemWatcher_Renamed(object sender, System.IO.RenamedEventArgs e)
        {
            File.AppendAllText(log_path, "Entered into fswatcher_renamed" + Environment.NewLine);
        }

        void fileSystemWatcher_Changed(object sender, System.IO.FileSystemEventArgs e)
        {
            File.AppendAllText(log_path, "Entered into fswatcher_changed" + Environment.NewLine);
        }

        void fileSystemWatcher_Deleted(object sender, System.IO.FileSystemEventArgs e)
        {
            File.AppendAllText(log_path, "Entered into fswatcher_deleted" + Environment.NewLine);
        }

        public static IntPtr CreateFileHandle(string driveLetter)
        {
            // open the existing file for reading          
            IntPtr handle = Win32.CreateFile(
                  driveLetter,
                  Win32.GENERIC_READ,
                  Win32.FILE_SHARE_READ | Win32.FILE_SHARE_WRITE,
                  0,
                  Win32.OPEN_EXISTING,
                  Win32.FILE_FLAG_BACKUP_SEMANTICS | Win32.FILE_ATTRIBUTE_NORMAL,
                  0);

            if (handle == Win32.INVALID_HANDLE_VALUE)
            {
                File.AppendAllText(log_path, "Return handle is null" + Environment.NewLine);
                return IntPtr.Zero;
            }
            else
            {
                File.AppendAllText(log_path, "Return handle is :" + handle + Environment.NewLine);
                return handle;
            }
        }

   protected override void OnStart(string[] args)
        {
            base.OnStart(args);

            //while (true)
            {
                File.WriteAllText(log_path, "Just entered to onstart for usbservice" + Environment.NewLine);
                RegisterDeviceNotification(log_path);
                File.AppendAllText(log_path, "Register Device Notification is ended" + Environment.NewLine);
                Win32.ServiceControlHandlerEx mycall = new Win32.ServiceControlHandlerEx(ServiceControlHandler);
                Win32.RegisterServiceCtrlHandlerEx(this.ServiceName, mycall, IntPtr.Zero);
                File.AppendAllText(log_path, "End" + Environment.NewLine);
            }
        }
public class Win32
        {
            public const int DEVICE_NOTIFY_SERVICE_HANDLE = 1;
            public const int DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 4;

            public const int SERVICE_CONTROL_STOP = 1;
            public const int SERVICE_CONTROL_DEVICEEVENT = 11;
            public const int SERVICE_CONTROL_SHUTDOWN = 5;

            public const uint GENERIC_READ = 0x80000000;
            public const uint OPEN_EXISTING = 3;
            public const uint FILE_SHARE_READ = 1;
            public const uint FILE_SHARE_WRITE = 2;
            public const uint FILE_SHARE_DELETE = 4;
            public const uint FILE_ATTRIBUTE_NORMAL = 128;
            public const uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
            public static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);

            public const int DBT_DEVTYP_DEVICEINTERFACE = 5;
            public const int DBT_DEVTYP_HANDLE = 6;

            public const int DBT_DEVICEARRIVAL = 0x8000;
            public const int DBT_DEVICEQUERYREMOVE = 0x8001;
            public const int DBT_DEVICEREMOVECOMPLETE = 0x8004;

            public const int WM_DEVICECHANGE = 0x219;

            public delegate int ServiceControlHandlerEx(int control, int eventType, IntPtr eventData, IntPtr context);

            [DllImport("advapi32.dll", SetLastError = true)]
            public static extern IntPtr RegisterServiceCtrlHandlerEx(string lpServiceName, ServiceControlHandlerEx cbex, IntPtr context);

            [DllImport("kernel32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool GetVolumePathNamesForVolumeNameW(
                    [MarshalAs(UnmanagedType.LPWStr)]
                    string lpszVolumeName,
                    [MarshalAs(UnmanagedType.LPWStr)]
                    string lpszVolumePathNames,
                    uint cchBuferLength,
                    ref UInt32 lpcchReturnLength);

            [DllImport("kernel32.dll")]
            public static extern bool GetVolumeNameForVolumeMountPoint(string
               lpszVolumeMountPoint, [Out] StringBuilder lpszVolumeName,
               uint cchBufferLength);

            [DllImport("user32.dll", SetLastError = true)]
            public static extern IntPtr RegisterDeviceNotification(IntPtr IntPtr, IntPtr NotificationFilter, Int32 Flags);

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

            [DllImport("kernel32.dll", SetLastError = true)]
            public 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.dll", SetLastError = true)]
            public static extern bool CloseHandle(IntPtr hObject);

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

            [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;
            }
        }