如何在Windows中获取COM端口的友好名称?

Ric*_*ACC 14 windows serial-port device-manager

我有一个通过USB连接的GSM调制解调器.调制解调器创建2个串行端口.第一个自动连接到调制解调器,第二个在设备管理器中显示为"HUAWEI Mobile Connect - 3G PC UI界面(COM6)"

第二个端口用于从调制解调器获取重要信息,例如信号质量; 发送和接收短信; 以及许多其他功能.

我正在编写一个应用程序,它将包含第二个端口提供的一些功能.我需要的是确定哪个COM端口是备用端口的确定的火灾方法.迭代端口并检查对"ATE0"的响应是不够的.调制解调器的端口通常是编号较小的端口,当拨号连接未激活时,它将响应"ATE0"与第二个端口相同.

我想要做的是迭代端口并检查它们的友好名称,如设备管理器中所示.这样我就可以将应用程序中的端口链接到设备管理器中标记为"HUAWEI Mobile Connect - 3G PC UI Interface(COM6)"的端口.我还没有找到任何可以让我以编程方式获得该名称的信息.

Wil*_*ean 8

很久以前我为客户写了一个实用工具来做这个,但是对于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, &regDataType, hardwareId, sizeof(hardwareId), NULL))
    {
...
Run Code Online (Sandbox Code Playgroud)

(你在循环中调用这个位并增加nDevice)

然后

BYTE friendlyName[300];
        if(SetupDiGetDeviceRegistryProperty(hDeviceInfo, &devInfoData, SPDRP_FRIENDLYNAME, NULL, friendlyName, sizeof(friendlyName), NULL))
        {
            strFriendlyNames += (LPCTSTR)friendlyName;
            strFriendlyNames += '\n';
        }
Run Code Online (Sandbox Code Playgroud)

找到设备的名称.

希望这能帮助您朝着正确的方向前进.


Ric*_*ACC 3

威尔·迪恩发布的信息非常有帮助。这是最终对我有用的代码。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;
}
Run Code Online (Sandbox Code Playgroud)

我认为这条线Result = tmpstring.Substring(tmpstring.IndexOf("COM"),tmpstring.IndexOf(')') - tmpstring.IndexOf("COM"));有点笨拙,有关如何清理它的建议将不胜感激。

感谢您对此事的帮助,如果没有您,我仍然会在谷歌上搜索。