通过串口设备vid,pid自动获得该设备所对应的串口号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | 用C#做串口通讯很方便,因为dotfx2.0已经集成了Serial Port控件,此控件使用上比MSComm控件更简单,当然它也有一个小bug (RecievedBytesThreshold设置有时候不好使),但是这个问题很好解决,而做串口通讯最最基本的问题就是如何获得目标机器的要与 之通讯的特定设备的特定com号,有许多软件在处理这个问题的时候都是要求用户手动去选择对应的串口号,这多少有些不人性化,这篇 文章就是介绍如何自动获得目标机器对应特定串口设备的串口号,从而达到软件与目标设备的自动通讯。 方法基本上是我前一篇文章的一个应用,代码如下(注意自己添加引用的命名空间) // <summary> /// 通过vid,pid获得串口设备号 /// </summary> /// <param name="vid">vid</param> /// <param name="pid">pid</param> /// <returns>串口号</returns> public static string GetPortNameFormVidPid( string vid, string pid) { Guid myGUID = Guid.Empty; string enumerator = "USB" ; try { IntPtr hDevInfo = HardWareLib.SetupDiGetClassDevs( ref myGUID, enumerator, IntPtr.Zero, HardWareLib.DIGCF_ALLCLASSES | HardWareLib.DIGCF_PRESENT); if (hDevInfo.ToInt32() == HardWareLib.INVALID_HANDLE_VALUE) { throw new Exception( "没有该类设备" ); } HardWareLib.SP_DEVINFO_DATA deviceInfoData; //想避免在api中使用ref,就把structure映射成类 deviceInfoData = new HardWareLib.SP_DEVINFO_DATA(); deviceInfoData.cbSize = 28; //如果要使用SP_DEVINFO_DATA,一定要给该项赋值28=16+4+4+4 deviceInfoData.devInst = 0; deviceInfoData.classGuid = System.Guid.Empty; deviceInfoData.reserved = 0; UInt32 i; StringBuilder property = new StringBuilder(HardWareLib.MAX_DEV_LEN); for (i = 0; HardWareLib.SetupDiEnumDeviceInfo(hDevInfo, i, deviceInfoData); i++) { // Console.Write(deviceInfoData.classGuid.ToString()); // HardWareOperation.SetupDiGetDeviceInstanceId(hDevInfo, deviceInfoData, porperty, (uint) porperty.Capacity, 0); HardWareLib.SetupDiGetDeviceRegistryProperty(hDevInfo, deviceInfoData, ( uint )HardWareLib.SPDRP_.SPDRP_CLASS, 0, property, ( uint )property.Capacity, IntPtr.Zero); if (property.ToString().ToLower() != "ports" ) continue ; //首先看看是不是串口设备(有些USB设备不是串口设备) HardWareLib.SetupDiGetDeviceRegistryProperty(hDevInfo, deviceInfoData, ( uint )HardWareLib.SPDRP_.SPDRP_HARDWAREID, 0, property, ( uint )property.Capacity, IntPtr.Zero); if (!(property.ToString().ToLower().Contains(vid.ToLower()) && property.ToString().ToLower().Contains(pid.ToLower()))) continue ; //找到对应于vid&pid的设备 HardWareLib.SetupDiGetDeviceRegistryProperty(hDevInfo, deviceInfoData, ( uint )HardWareLib.SPDRP_.SPDRP_FRIENDLYNAME, 0, property, ( uint )property.Capacity, IntPtr.Zero); break ; } HardWareLib.SetupDiDestroyDeviceInfoList(hDevInfo); //记得用完释放相关内存 string friendlyName = property.ToString(); string pattern= @"(COM[1-9][0-9]?)$" ; //friendlyName一般形式为以(COMn)结尾,n为1-99 if (Regex.IsMatch(friendlyName, pattern, RegexOptions.IgnoreCase)) { string portName=Regex.Match(friendlyName, pattern, RegexOptions.IgnoreCase).Value; return portName.Trim( new char [] { '(' , ')' }); } return null ; } catch (Exception ex) { MessageBox.Show(ex.Message); return null ; } } HardWareLib.cs(也就是前一篇文章的一个类) using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace ForGeneralUse { public class HardWareLib { /// <summary> /// 设备的各项属性,注意有些属性是不通用的,例如SPDRP_FRIENDLYNAME只适用于端口设备 /// </summary> public enum SPDRP_ { SPDRP_DEVICEDESC = (0x00000000), // DeviceDesc (R/W) SPDRP_HARDWAREID = (0x00000001), // HardwareID (R/W) SPDRP_SERVICE = (0x00000004), // Service (R/W) SPDRP_CLASS = (0x00000007), // Class (R--tied to ClassGUID) SPDRP_CLASSGUID = (0x00000008), // ClassGUID (R/W) SPDRP_DRIVER = (0x00000009), // Driver (R/W) SPDRP_CONFIGFLAGS = (0x0000000A), // ConfigFlags (R/W) SPDRP_MFG = (0x0000000B), // Mfg (R/W) SPDRP_FRIENDLYNAME = (0x0000000C), // FriendlyName (R/W) SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = (0x0000000E), // PhysicalDeviceObjectName (R) SPDRP_CAPABILITIES = (0x0000000F), // Capabilities (R) SPDRP_REMOVAL_POLICY_HW_DEFAULT = (0x00000020), // Hardware Removal Policy (R) SPDRP_INSTALL_STATE = (0x00000022), // Device Install State (R) } public const int DIGCF_ALLCLASSES = (0x00000004); public const int DIGCF_DEVICEINTERFACE = 0x00000010; public const int DIGCF_PRESENT = (0x00000002); public const int INVALID_HANDLE_VALUE = -1; public const int MAX_DEV_LEN = 1000; /// <summary> /// 获取一个指定类别或全部类别的所有已安装设备的信息 /// </summary> /// <param name="gClass">该类别对应的guid</param> /// <param name="iEnumerator">类别名称(在HKLMSYSTEMCurrentControlSetEnum内获取)</param> /// <param name="hParent">应用程序定义的窗口句柄</param> /// <param name="nFlags">获取的模式</param> /// <returns>设备信息集合的句柄</returns> [DllImport( "setupapi.dll" , SetLastError = true , CharSet = CharSet.Auto)] public static extern IntPtr SetupDiGetClassDevs( ref Guid gClass, String enumerator, IntPtr hParent, UInt32 nFlags); /// <summary> /// 获得该设备的设备范例ID /// </summary> /// <param name="DeviceInfoSet">设备信息集合</param> /// <param name="DeviceInfoData">表示该设备</param> /// <param name="DeviceInstanceId">设备范例ID(输出)</param> /// <param name="DeviceInstanceIdSize">该ID所占大小(字节)</param> /// <param name="RequiredSize">需要多少字节</param> /// <returns>是否成功</returns> DllImport( "setupapi.dll" , SetLastError = true )] public static extern bool SetupDiGetDeviceInstanceId(IntPtr DeviceInfoSet, HardWareLib.SP_DEVINFO_DATA DeviceInfoData, StringBuilder DeviceInstanceId, UInt32 DeviceInstanceIdSize, UInt32 RequiredSize); /// <summary> /// 枚举指定设备信息集合的成员,并将数据放在SP_DEVINFO_DATA中 /// </summary> /// <param name="lpInfoSet">设备信息集合句柄</param> /// <param name="dwIndex">元素索引</param> /// <param name="devInfoData">表示一个设备(作为输出)</param> /// <returns>是否成功</returns> [DllImport( "setupapi.dll" , SetLastError = true )] public static extern bool SetupDiEnumDeviceInfo(IntPtr lpInfoSet, UInt32 dwIndex, SP_DEVINFO_DATA devInfoData); // <summary> /// 获取指定设备的属性 /// </summary> /// <param name="lpInfoSet">设备信息集合</param> /// <param name="DeviceInfoData">表示该设备</param> /// <param name="Property">表示要获取哪项属性</param> /// <param name="PropertyRegDataType">注册类型</param> /// <param name="PropertyBuffer">属性(输出)</param> /// <param name="PropertyBufferSize">存储属性的字节大小</param> /// <param name="RequiredSize">需要的字节大小</param> /// <returns>是否成功</returns> [DllImport( "setupapi.dll" , SetLastError = true )] public static extern bool SetupDiGetDeviceRegistryProperty(IntPtr lpInfoSet, SP_DEVINFO_DATA DeviceInfoData, UInt32 Property, UInt32 PropertyRegDataType, StringBuilder PropertyBuffer, UInt32 PropertyBufferSize, IntPtr RequiredSize); /// <summary> /// 销毁一个设备信息集合,并且释放所有关联的内存 /// </summary> /// <param name="lpInfoSet">设备信息集合</param> /// <returns></returns> [DllImport( "setupapi.dll" , SetLastError = true )] public static extern bool SetupDiDestroyDeviceInfoList(IntPtr lpInfoSet); /// <summary> /// 设备信息数据 /// </summary> [StructLayout(LayoutKind.Sequential)] public class SP_DEVINFO_DATA { public int cbSize; //本结构的大小(字节表示) public Guid classGuid; //本结构所表示的设备的GUID public int devInst; //设备句柄 public ulong reserved; //没用 }; } } 如果大家想了解正则表达式的简单使用,推荐大家访问如下网址 http: //www.szwblm.com/Netvb/ShowArticle.asp?ArticleID=19633, http: //www.szwblm.com/Netvb/ShowArticle.asp?ArticleID=14918<br><br>本文来自转载,小编尚未尝试,静待。。。 |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步