C# USB设备接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Management;                          /* System.Management referenced */
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;

namespace TestBoardDriver
{
    public class DevManager
    {
        private static List<int> portNums = new List<int>();
        private static List<string> portIds = new List<string>();

        private static string GetPortId(int portNum)
        {
            for (int i = 0; i < portNums.Count; i++)
            {
                if (portNums[i] == portNum)
                {
                    return portIds[i];
                }
            }

            return "NA";
        }
        /*
            自动查找VID/PID匹配的USB设备当作Virutal COM Port口 
            输入值:   字符串,如VID_0483&PID_5740
            返回值:   0 - 没有找到对应设备
        */
        public static List<int> GetPortNum(String vid_pid)
        {
            ManagementObjectCollection USBControllerDeviceCollection
                = new ManagementObjectSearcher("SELECT * FROM Win32_USBControllerDevice").Get();
            if (USBControllerDeviceCollection != null)
            {
                foreach (ManagementObject USBControllerDevice in USBControllerDeviceCollection)
                {
                    String Dependent = (USBControllerDevice["Dependent"] as String).Split(new Char[] { '=' })[1];     

                    if (Dependent.Contains(vid_pid))
                    {
                        ManagementObjectCollection PnPEntityCollection
                            = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE DeviceID=" + Dependent).Get();
                        if (PnPEntityCollection != null)
                        {
                            foreach (ManagementObject Entity in PnPEntityCollection)
                            {
                                
                                String PortId = Dependent.Split('\\')[4];           //Dependent = ""USB\\VID_0483&PID_5740\\6D8D108F5750""
                                PortId = PortId.Substring(0, PortId.Length - 1);

                                String DevName = Entity["Name"] as String;          // 设备名称 = "STMicroelectronics Virtual COM Port (COM9)"
                                String PortNum = Regex.Replace(DevName, @"[^\d.\d]", "");

                                try
                                {/*安装驱动程序过慢会导致DevName中不含COM号(出现概率小)*/
                                    portNums.Add( Convert.ToInt32(PortNum) );
                                    portIds.Add(PortId);
                                }
                                catch(Exception)
                                {
                                    return GetPortNum(vid_pid);
                                }
                            }
                        }
                    }
                }
            }

            return portNums;
        }

        /*
            删除指定设备 
            输入值:   设备管理器下的设备名称,不包括后面的(COMXX)
            返回值:   成功/失败
        */
        public static bool DeletePort(String vidpid, int comNum)
        {
            bool ret = false;

            Guid classGuid = Guid.Empty;
            IntPtr hDevInfo = Win32.SetupDiGetClassDevs(ref classGuid, null, IntPtr.Zero, Win32.DIGCF_ALLCLASSES | Win32.DIGCF_PRESENT);
            if (hDevInfo.ToInt32() == Win32.INVALID_HANDLE_VALUE)
            {
                Console.WriteLine("访问硬件设备失败");
            }
            else
            {
                string portId = GetPortId(comNum);

                int i = 0;
                int selected = 0;

                StringBuilder deviceName = new StringBuilder();
                deviceName.Capacity = Win32.MAX_DEV_LEN;
                do
                {
                    Win32.SP_DEVINFO_DATA devInfoData = new Win32.SP_DEVINFO_DATA();
                    StringBuilder _DeviceName = new StringBuilder("");
                    _DeviceName.Capacity = 1000;

                    devInfoData.cbSize = Marshal.SizeOf(typeof(Win32.SP_DEVINFO_DATA));
                    devInfoData.classGuid = Guid.Empty;
                    devInfoData.devInst = 0;
                    devInfoData.reserved = IntPtr.Zero;
                    bool result = Win32.SetupDiEnumDeviceInfo(hDevInfo, i, devInfoData);
                    if (false == result)
                    {
                        break;
                    }

                    Win32.SetupDiGetDeviceRegistryProperty(hDevInfo, devInfoData, 0, 0, _DeviceName, (uint)_DeviceName.Capacity, IntPtr.Zero);

                    string devId = GetDeviceInstanceId(hDevInfo, devInfoData);
                    if (devId.Contains(vidpid))
                    {
                        if (devId.Contains(portId))
                        {
                            Log.Show(Log.Level.Operation, "Deleting " + _DeviceName.ToString() + " " + comNum + " :" + devId);
                            selected = i;
                        }
                    }
                    ++i;
                } while (true);

                ret = Remove(selected, hDevInfo);

            }
            Win32.SetupDiDestroyDeviceInfoList(hDevInfo);

            return ret;
        }

        /*
            重新扫描硬件 
            输入值:   无
            返回值:   成功/失败
        */
        public static bool Rescan()
        {
            UInt32 devRoot = 0;

            if (Win32.CM_Locate_DevNode_Ex(ref devRoot, null, 0, IntPtr.Zero) != Win32.CR_SUCCESS)
            {
                return false;
            }
            if (Win32.CM_Reenumerate_DevNode_Ex(devRoot, 0, IntPtr.Zero) != Win32.CR_SUCCESS)
            {
                return false;
            }

            return true;
        }
        /*
            禁用指定设备 
            输入值:   设备管理器下的设备名称,不包括后面的(COMXX)
            返回值:   成功/失败
        */
        public static bool DisablePort(String portName = null)
        {
            bool ret = false;

            Guid classGuid = Guid.Empty;
            IntPtr hDevInfo = Win32.SetupDiGetClassDevs(ref classGuid, null, IntPtr.Zero, Win32.DIGCF_ALLCLASSES | Win32.DIGCF_PRESENT);
            if (hDevInfo.ToInt32() == Win32.INVALID_HANDLE_VALUE)
            {
                Console.WriteLine("访问硬件设备失败");
            }
            else
            {
                int i = 0;
                int selected = 0;

                StringBuilder deviceName = new StringBuilder();
                deviceName.Capacity = Win32.MAX_DEV_LEN;
                do
                {
                    Win32.SP_DEVINFO_DATA devInfoData = new Win32.SP_DEVINFO_DATA();
                    StringBuilder _DeviceName = new StringBuilder("");
                    _DeviceName.Capacity = 1000;

                    devInfoData.cbSize = Marshal.SizeOf(typeof(Win32.SP_DEVINFO_DATA));
                    devInfoData.classGuid = Guid.Empty;
                    devInfoData.devInst = 0;
                    devInfoData.reserved = IntPtr.Zero;
                    bool result = Win32.SetupDiEnumDeviceInfo(hDevInfo, i, devInfoData);
                    if (false == result)
                    {
                        break;
                    }

                    Win32.SetupDiGetDeviceRegistryProperty(hDevInfo, devInfoData, 0, 0, _DeviceName, (uint)_DeviceName.Capacity, IntPtr.Zero);
                    
                    if (_DeviceName.ToString().Equals(portName))
                    {
                        Log.Show(Log.Level.Operation, _DeviceName.ToString());
                        selected = i;
                    }
                    ++i;
                } while (true);

                ret = StateChange(false, selected, hDevInfo);

            }
            Win32.SetupDiDestroyDeviceInfoList(hDevInfo);

            return ret;
        }

        private static bool Remove(int SelectedItem, IntPtr DevInfo)
        {
            bool result = false;
            Win32.SP_DEVINFO_DATA devInfoData = new Win32.SP_DEVINFO_DATA(); ;
            devInfoData.cbSize = Marshal.SizeOf(typeof(Win32.SP_DEVINFO_DATA));
            if (true == Win32.SetupDiEnumDeviceInfo(DevInfo, SelectedItem, devInfoData))
            {
                if (true == Win32.SetupDiCallClassInstaller(Win32.DIF_REMOVE, DevInfo, devInfoData))
                {
                    result = true;
                }
                else
                {
                    uint ret = (uint)Win32.GetLastError();
                    Log.Show(Log.Level.Operation, "删除硬件设备失败(" + ret.ToString() + ")");
                }
            }
            return result;
        }
        private static bool StateChange(bool Enable, int SelectedItem, IntPtr DevInfo)
        {
            bool result = false;
            Win32.SP_DEVINFO_DATA devInfoData = new Win32.SP_DEVINFO_DATA(); ;
            devInfoData.cbSize = Marshal.SizeOf(typeof(Win32.SP_DEVINFO_DATA));
            if (true == Win32.SetupDiEnumDeviceInfo(DevInfo, SelectedItem, devInfoData))
            {
                Win32.SP_PROPCHANGE_PARAMS pcp = new Win32.SP_PROPCHANGE_PARAMS(); ;
                pcp.ClassInstallHeader.cbSize = Marshal.SizeOf(typeof(Win32.SP_CLASSINSTALL_HEADER));
                pcp.ClassInstallHeader.InstallFunction = Win32.DIF_PROPERTYCHANGE;
                pcp.Scope = Win32.DICS_FLAG_CONFIGSPECIFIC;
                pcp.StateChange = (Enable ? Win32.DICS_ENABLE : Win32.DICS_DISABLE);
                if (true == Win32.SetupDiSetClassInstallParams(DevInfo, devInfoData, pcp, Marshal.SizeOf(pcp)))
                {
                    if (true == Win32.SetupDiCallClassInstaller(Win32.DIF_PROPERTYCHANGE, DevInfo, devInfoData))
                    {
                        result = true;
                    }
                    else
                    {
                        uint ret = (uint)Win32.GetLastError();
                        Log.Show(Log.Level.Operation, "禁用硬件设备失败(" + ret.ToString() + ")");
                    }
                }
            }
            return result;
        }

        protected static String GetClassNameFromGuid(Guid guid)
        {
            String result = String.Empty;
            StringBuilder className = new StringBuilder();
            Int32 iRequiredSize = 0;
            Int32 iSize = 0;
            bool b = Win32.SetupDiClassNameFromGuid(ref guid, className, iSize, ref iRequiredSize);

            className = new StringBuilder(iRequiredSize);
            iSize = iRequiredSize;

            b = Win32.SetupDiClassNameFromGuid(ref guid, className, iSize, ref iRequiredSize);
            if (true == b)
            {
                result = className.ToString();
            }
            return result;
        }
        protected static String GetClassDescriptionFromGuid(Guid guid)
        {
            String result = String.Empty;
            StringBuilder classDesc = new StringBuilder(0);
            Int32 iRequiredSize = 0;
            Int32 iSize = 0;
            bool b = Win32.SetupDiGetClassDescription(ref guid, classDesc, iSize, ref iRequiredSize);

            classDesc = new StringBuilder(iRequiredSize);
            iSize = iRequiredSize;

            b = Win32.SetupDiGetClassDescription(ref guid, classDesc, iSize, ref iRequiredSize);
            if (true == b)
            {
                result = classDesc.ToString();
            }
            return result;
        }
        protected static String GetDeviceInstanceId(IntPtr DeviceInfoSet, Win32.SP_DEVINFO_DATA DeviceInfoData)
        {
            String result = String.Empty;
            StringBuilder id = new StringBuilder(0);
            Int32 iRequiredSize = 0;
            Int32 iSize = 0;
            bool b = Win32.SetupDiGetDeviceInstanceId(DeviceInfoSet, DeviceInfoData, id, iSize, ref iRequiredSize);

            id = new StringBuilder(iRequiredSize);
            iSize = iRequiredSize;

            b = Win32.SetupDiGetDeviceInstanceId(DeviceInfoSet, DeviceInfoData, id, iSize, ref iRequiredSize);
            if (true == b)
            {
                result = id.ToString();
            }
            return result;
        }

        /* setupapi.dll elements */
        public class Win32
        {
            [StructLayout(LayoutKind.Sequential)]
            public struct SP_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;
            }

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

            [StructLayout(LayoutKind.Sequential)]
            public class SP_DEVINFO_DATA
            {
                public int cbSize;
                public Guid classGuid;
                public int devInst;
                public IntPtr reserved;
            };

            [StructLayout(LayoutKind.Sequential)]
            public class SP_DEVINSTALL_PARAMS
            {
                public int cbSize;
                public int Flags;
                public int FlagsEx;
                public IntPtr hwndParent;
                public IntPtr InstallMsgHandler;
                public IntPtr InstallMsgHandlerContext;
                public IntPtr FileQueue;
                public IntPtr ClassInstallReserved;
                public int Reserved;
                [MarshalAs(UnmanagedType.LPTStr)]
                public string DriverPath;
            };

            [StructLayout(LayoutKind.Sequential)]
            public class SP_PROPCHANGE_PARAMS
            {
                public SP_CLASSINSTALL_HEADER ClassInstallHeader = new SP_CLASSINSTALL_HEADER();
                public int StateChange;
                public int Scope;
                public int HwProfile;
            };

            [StructLayout(LayoutKind.Sequential)]
            public class SP_CLASSINSTALL_HEADER
            {
                public int cbSize;
                public int InstallFunction;
            };

            [DllImport("kernel32.dll")]
            public static extern uint GetLastError();
            [DllImport("user32.dll", CharSet = CharSet.Auto)]
            public static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, DEV_BROADCAST_DEVICEINTERFACE NotificationFilter, UInt32 Flags);

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

            [DllImport("setupapi.dll", SetLastError = true)]
            public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid,
            [MarshalAs(UnmanagedType.LPStr)]String Enumerator, IntPtr hwndParent, Int32 Flags);

            [DllImport("setupapi.dll")]
            public static extern IntPtr SetupDiGetClassDevsEx(ref Guid ClassGuid,
            [MarshalAs(UnmanagedType.LPStr)]String Enumerator,
            IntPtr hwndParent, Int32 Flags, IntPtr DeviceInfoSet,
            [MarshalAs(UnmanagedType.LPStr)]String MachineName,
            IntPtr Reserved);

            [DllImport("setupapi.dll", SetLastError = true)]
            public static extern Int32 SetupDiDestroyDeviceInfoList(IntPtr lpInfoSet);

            [DllImport("setupapi.dll", SetLastError = true)]
            public static extern Boolean SetupDiEnumDeviceInfo(IntPtr lpInfoSet, Int32 dwIndex, SP_DEVINFO_DATA devInfoData);

            [DllImport("setupapi.dll", SetLastError = true)]
            public static extern Boolean SetupDiGetDeviceRegistryProperty(IntPtr lpInfoSet, SP_DEVINFO_DATA DeviceInfoData, UInt32 Property,
            UInt32 PropertyRegDataType, StringBuilder PropertyBuffer, UInt32 PropertyBufferSize, IntPtr RequiredSize);

            [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
            public static extern Boolean SetupDiSetClassInstallParams(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, SP_PROPCHANGE_PARAMS ClassInstallParams, int ClassInstallParamsSize);

            [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
            public static extern Boolean SetupDiCallClassInstaller(UInt32 InstallFunction, IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData);
            [DllImport("newdev.dll", CharSet = CharSet.Auto)]
            public static extern Boolean DiUninstallDevice(IntPtr parent, IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, IntPtr flag, bool reboot);
            [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
            public static extern Boolean SetupDiRemoveDevice(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData);
            [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
            public static extern Boolean SetupDiUnremoveDevice(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData);

            [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
            public static extern Boolean SetupDiClassNameFromGuid(ref Guid ClassGuid, StringBuilder className, Int32 ClassNameSize, ref Int32 RequiredSize);

            [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
            public static extern Boolean SetupDiGetClassDescription(ref Guid ClassGuid, StringBuilder classDescription, Int32 ClassDescriptionSize, ref Int32 RequiredSize);

            [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
            public static extern Boolean SetupDiGetDeviceInstanceId(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, StringBuilder DeviceInstanceId, Int32 DeviceInstanceIdSize, ref Int32 RequiredSize);

            [DllImport("setupapi.dll", SetLastError = true)]
            public static extern bool SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, int Property, uint PropertyRegDataType, StringBuilder PropertyBuffer, uint PropertyBufferSize, IntPtr RequiredSize);

            public const int DIGCF_ALLCLASSES = (0x00000004);
            public const int DIGCF_PRESENT = (0x00000002);
            public const int INVALID_HANDLE_VALUE = -1;
            public const int SPDRP_DEVICEDESC = (0x00000000);
            public const int MAX_DEV_LEN = 200;
            public const int DEVICE_NOTIFY_WINDOW_HANDLE = (0x00000000);
            public const int DEVICE_NOTIFY_SERVICE_HANDLE = (0x00000001);
            public const int DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = (0x00000004);
            public const int DBT_DEVTYP_DEVICEINTERFACE = (0x00000005);
            public const int DBT_DEVNODES_CHANGED = (0x0007);
            public const int WM_DEVICECHANGE = (0x0219);
            public const int DIF_REMOVE = (0x00000005);
            public const int DIF_PROPERTYCHANGE = (0x00000012);
            public const int DICS_FLAG_GLOBAL = (0x00000001);
            public const int DICS_FLAG_CONFIGSPECIFIC = (0x00000002);
            public const int DICS_ENABLE = (0x00000001);
            public const int DICS_DISABLE = (0x00000002);

            [DllImport("setupapi.dll", SetLastError = true)]
            static public extern int CM_Locate_DevNode_Ex(ref UInt32 pdnDevInst, string pDeviceID, int ulFlags, IntPtr hMachine);
            [DllImport("setupapi.dll")]
            static public extern UInt32 CM_Reenumerate_DevNode_Ex(UInt32 dnDevInst, UInt32 ulFlags, IntPtr hMachine);
            public const uint CR_SUCCESS = 0x00000000;
        }
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值