我有一个通过USB连接的GSM调制解调器。 调制解调器创build2个串行端口。 第一个自动连接到调制解调器,第二个在设备pipe理器中显示为“HUAWEI Mobile Connect – 3G PC UI Interface(COM6)”
第二个端口用于获取调制解调器的重要信息,如信号质量; 发送和接收短信; 和其他一些function。
我正在编写一个应用程序,将包装由第二个端口提供的一些function。 我需要的是确定哪个COM端口是备用端口的确定的火灾方法。 迭代端口并检查对“ATE0”的响应是不够的。 调制解调器的端口通常是编号较小的端口,拨号连接没有激活时,它将响应“ATE0”和第二个端口相同。
我正在考虑的是迭代端口并检查它们的友好名称,如在设备pipe理器中所示。 这样我可以将我的应用程序中的端口连接到设备pipe理器中标有“HUAWEI Mobile Connect – 3G PC UI Interface(COM6)”的端口。 我还没有find任何信息,这将允许我以编程方式获得该名称。
很久以前,我为客户写了一个实用程序来做这件事,但是为了GPS而不是调制解调器。
我刚才看了一下,跳出来可能有帮助的是:
GUID guid = GUID_DEVCLASS_PORTS; SP_DEVICE_INTERFACE_DATA interfaceData; ZeroMemory(&interfaceData, sizeof(interfaceData)); interfaceData.cbSize = sizeof(interfaceData); SP_DEVINFO_DATA devInfoData; ZeroMemory(&devInfoData, sizeof(devInfoData)); devInfoData.cbSize = sizeof(devInfoData); if(SetupDiEnumDeviceInfo( hDeviceInfo, // Our device tree nDevice, // The member to look for &devInfoData )) { DWORD regDataType; BYTE hardwareId[300]; if(SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, ®DataType, hardwareId, sizeof(hardwareId), NULL)) { ...
(你可以在增加nDevice的循环中调用这个位)
接着
BYTE friendlyName[300]; if(SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, NULL, friendlyName, sizeof(friendlyName), NULL)) { strFriendlyNames += (LPCTSTR)friendlyName; strFriendlyNames += '\n'; }
找到设备的名称。
希望这会帮助你在正确的方向。
当你确定一个串口设备是你想要的(通过查看它的友好名称,通过检查它的父设备等),获取端口名称的正确方法可能是:
SetupDiOpenDevRegKey(hDevInfo, devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ)
将HKEY
获取到所谓的设备密钥 REG_SZ
值“PortName” HKEY
🙂 但是,这可能需要在C#中进行太多的互操作,所以我不会怪你,如果你坚持字符串解析的解决方案。
Will Dean发布的信息是最有帮助的。 这是最终为我工作的代码。 PInvoke类中的所有内容都是从http://www.pinvoke.net逐字记录的。 我不得不改变一个数据类型在这里或那里使其工作(如使用枚举而不是一个uint),但它应该很容易弄清楚。
internal static string GetComPortByDescription(string Description) { string Result = string.Empty; Guid guid = PInvoke.GUID_DEVCLASS_PORTS; uint nDevice = 0; uint nBytes = 300; byte[] retval = new byte[nBytes]; uint RequiredSize = 0; uint PropertyRegDataType = 0; PInvoke.SP_DEVINFO_DATA devInfoData = new PInvoke.SP_DEVINFO_DATA(); devInfoData.cbSize = Marshal.SizeOf(typeof(PInvoke.SP_DEVINFO_DATA)); IntPtr hDeviceInfo = PInvoke.SetupDiGetClassDevs( ref guid, null, IntPtr.Zero, PInvoke.DIGCF.DIGCF_PRESENT); while (PInvoke.SetupDiEnumDeviceInfo(hDeviceInfo, nDevice++, ref devInfoData)) { if (PInvoke.SetupDiGetDeviceRegistryProperty( hDeviceInfo, ref devInfoData, PInvoke.SPDRP.SPDRP_FRIENDLYNAME, out PropertyRegDataType, retval, nBytes, out RequiredSize)) { if (System.Text.Encoding.Unicode.GetString(retval).Substring(0, Description.Length).ToLower() == Description.ToLower()) { string tmpstring = System.Text.Encoding.Unicode.GetString(retval); Result = tmpstring.Substring(tmpstring.IndexOf("COM"),tmpstring.IndexOf(')') - tmpstring.IndexOf("COM")); } // if retval == description } // if (PInvoke.SetupDiGetDeviceRegistryProperty( ... SPDRP_FRIENDLYNAME ... } // while (PInvoke.SetupDiEnumDeviceInfo(hDeviceInfo, nDevice++, ref devInfoData)) PInvoke.SetupDiDestroyDeviceInfoList(hDeviceInfo); return Result; }
我认为行Result = tmpstring.Substring(tmpstring.IndexOf("COM"),tmpstring.IndexOf(')') - tmpstring.IndexOf("COM"));
是有点笨拙,建议如何清理它将不胜感激。
感谢您对这件事的帮助Will,没有你,我仍然在搜索谷歌。
很高兴工作。
你可以尝试:
Regex.Match(tmpstring,@“COM \ s \ d +”)。ToString()
为你的字符串匹配。
作为.NET的风格点,我会添加一个“使用System.Text”,我不会开始使用大写的局部变量名称,如果我真的感觉良性,我可能会把SetupDiDestroyDeviceInfoList放在一个finally {}子句。
使用李根臣发表的方法。 ComPortSetupAPISetupDiClassGuids方法给了最好的时间和友好的名字。
基于@Will Dean的C ++版本答案。
#include <windows.h> #include <initguid.h> #include <devguid.h> #include <setupapi.h> void enumerateSerialPortsFriendlyNames() { SP_DEVINFO_DATA devInfoData = {}; devInfoData.cbSize = sizeof(devInfoData); // get the tree containing the info for the ports HDEVINFO hDeviceInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 0, nullptr, DIGCF_PRESENT ); if (hDeviceInfo == INVALID_HANDLE_VALUE) { return; } // iterate over all the devices in the tree int nDevice = 0; while (SetupDiEnumDeviceInfo(hDeviceInfo, // Our device tree nDevice++, // The member to look for &devInfoData)) { DWORD regDataType; DWORD reqSize = 0; // find the size required to hold the device info SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, nullptr, nullptr, 0, &reqSize); BYTE hardwareId[reqSize > 1 ? reqSize : 1]; // now store it in a buffer if (SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_HARDWAREID, ®DataType, hardwareId, sizeof(hardwareId), nullptr)) { // find the size required to hold the friendly name reqSize = 0; SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, nullptr, 0, &reqSize); BYTE friendlyName[reqSize > 1 ? reqSize : 1]; // now store it in a buffer if (!SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, nullptr, friendlyName, sizeof(friendlyName), nullptr)) { // device does not have this property set memset(friendlyName, 0, reqSize > 1 ? reqSize : 1); } // use friendlyName here } } }