如何在Windows中获得COM端口的友好名称?
我有一个通过USB连接的GSM调制解调器。调制解调器创建2个串行端口。第一个端口自动连接到调制解调器,第二个端口在设备管理器中显示为“HUAWEI Mobile Connect - 3G PC UI接口(COM6)”如何在Windows中获得COM端口的友好名称?
第二个端口用于获取调制解调器的重要信息,如信号质量;发送和接收短信;和许多其他功能。
我正在编写一个应用程序,它将包装第二个端口提供的一些功能。我需要的是确定哪个COM端口是备用端口的确定火灾方法。迭代端口并检查对“ATE0”的响应是不够的。调制解调器的端口通常是编号较小的端口,当拨号连接未激活时,它将响应“ATE0”,与第二个端口相同。
我在做的是迭代端口并检查它们的友好名称,如在设备管理器中显示的那样。这样我可以将我的应用程序中的端口连接到设备管理器中标有“HUAWEI Mobile Connect - 3G PC UI Interface(COM6)”的端口。我还没有找到任何信息可以让我以编程方式获得该名称。
很久以前,我为客户写了一个实用程序来做这件事,但对于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))
{
...
(你调用一个循环此位与递增n设备)
然后
BYTE friendlyName[300];
if(SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, NULL, friendlyName, sizeof(friendlyName), NULL))
{
strFriendlyNames += (LPCTSTR)friendlyName;
strFriendlyNames += '\n';
}
它找到设备的名称。
希望这会帮助你在正确的方向。
发布的信息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"));
有一点笨拙,如何清理建议,将不胜感激。
感谢您对此事的帮助请问,没有您,我仍然在搜索谷歌。
很高兴工作。
你可以尝试:
Regex.Match(tmpstring,@ “COM \ S \ d +”)的ToString()
您的字符串匹配。我会添加一个“using System.Text”,并且我不会用大写字母开始局部变量名称,如果我感觉真正有道理,我可能会将SetupDiDestroyDeviceInfoList放入一个终于{}子句。
正则表达式看起来更优雅。有一件事我不得不改变:“COM \ s?\ d +”COM和数字之间不会有空格,所以它需要匹配0或更多。 再次感谢。 – RichieACC 2008-11-21 09:05:15
在确定串行端口的设备是你想要(通过查看其友好的名称,通过检查其父设备等)的人,正确的方式来获得端口的名称很可能是:
- 调用
SetupDiOpenDevRegKey(hDevInfo, devInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ)
得到HKEY
到所谓的设备密钥 - 查询为
REG_SZ
值“端口名”此注册表项 - 不要忘记关闭
HKEY
:)
但是,这可能需要在C#中进行如此多的互操作,这甚至不好笑,所以如果你坚持字符串解析解决方案,我不会责怪你。
基于@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
}
}
}
这看起来可能只是伎俩。我正在写一个测试。感谢百万:) – RichieACC 2008-11-20 11:53:43