首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过安装API获得一致的列表?

如何通过安装API获得一致的列表?
EN

Stack Overflow用户
提问于 2019-03-11 15:30:54
回答 1查看 268关注 0票数 0

前面的一句话是:大部分文本和代码如下所示,但我试图尽可能详细地解释我的问题(这是随机发生的):

我的应用程序通过安装API处理网络接口,随机失败,很可能是在尝试使用SetupDiGetDeviceRegistryProperty()时。我遇到的主要问题是SetupDiEnumDeviceInfo()返回的设备列表(我用它来获取将传递给SetupDiGetDeviceRegistryProperty()的特定网络适配器的索引)以“意外”的方式改变。我的第一个问题是设备出现并/或从这个列表中消失。正如这里所说的,我发现第一件事是使用

代码语言:javascript
复制
const GUID *netGUID = &GUID_DEVCLASS_NET;    
SetupDiGetClassDevs(netGUID, 0, 0, DIGCF_PROFILE)

而不是

代码语言:javascript
复制
const GUID *netGUID = &GUID_DEVCLASS_NET;
SetupDiGetClassDevs(netGUID, 0, 0, DIGCF_PRESENT)

始终返回设备管理器中可以看到的所有网络适配器(包括“隐藏”=“未安装”)。在Windows 10 (64位)中,这一功能如预期的那样有效。

很高兴它能工作,我编译了该应用程序,以便与Windows 7 32位一起使用,并对其进行了测试。不幸的是,我必须看到仍然存在一个问题大多数时候我都会

代码语言:javascript
复制
WAN Miniport (IP), WAN Miniport (IPv6), WAN Miniport (PPPOE), Microsoft ISATAP Adapter, Microsoft ISATAP Adapter #2, WAN Miniport (PPTP), Microsoft ISATAP Adapter #3, WAN Miniport (SSTP), Intel(R) I210 Gigabit Network Connection, Intel(R) Ethernet Connection I219-LM, RAS Async Adapter, WAN Miniport (IKEv2), WAN Miniport (L2TP), WAN Miniport (Network Monitor)

但有时顺序会这样改变:

代码语言:javascript
复制
Intel(R) I210 Gigabit Network Connection,Intel(R) Ethernet Connection I219-LM,Microsoft ISATAP Adapter,Microsoft ISATAP Adapter #2,Microsoft ISATAP Adapter #3,WAN Miniport (IKEv2),WAN Miniport (L2TP),WAN Miniport (Network Monitor),WAN Miniport (IP),WAN Miniport (IPv6),WAN Miniport (PPPOE),WAN Miniport (PPTP),WAN Miniport (SSTP),RAS Async Adapter

使用下面的(Qt)代码可能会导致我确定的索引不再与预期的设备匹配。有没有办法防止设备列表的顺序发生变化,还是我做错了什么?

代码语言:javascript
复制
// Get a list of all network adpters known by the system
const QStringList adapterNames()
{
    HDEVINFO hIfDevs;
    quint32 index = 0;
    SP_DEVINFO_DATA infoData;
    const GUID *netGUID = &GUID_DEVCLASS_NET;
    QStringList adapterNames = QStringList();
    CHAR friendlyName[MAX_DEVICE_NAME];

    hIfDevs = SetupDiGetClassDevs(netGUID, 0, 0, DIGCF_PRESENT);

    if (hIfDevs == INVALID_HANDLE_VALUE)
    {
        qWarning() << "Getting device class info failed with error " << GetLastError();
        return QStringList();
    }

    SecureZeroMemory(&infoData, sizeof(SP_DEVINFO_DATA));
    infoData.cbSize = sizeof(SP_DEVINFO_DATA);

    while (SetupDiEnumDeviceInfo(hIfDevs, index, &infoData))
    {
        SecureZeroMemory(friendlyName, sizeof(friendlyName));

        if (!SetupDiGetDeviceRegistryPropertyA(hIfDevs, &infoData, SPDRP_FRIENDLYNAME, NULL, (LPBYTE)friendlyName, MAX_DEVICE_NAME, NULL))
        {
            if (!SetupDiGetDeviceRegistryPropertyA(hIfDevs, &infoData, SPDRP_DEVICEDESC, NULL, (LPBYTE)friendlyName, MAX_DEVICE_NAME, NULL))
            {
                qWarning() << "SetupDiGetDeviceRegistryPropertyA() for #" << index << "returned error " << GetLastError();
            }
        }

        if(friendlyName[0])
        {
            adapterNames.append(QString::fromLocal8Bit(friendlyName));
        }

        index++;
    }

SetupDiDestroyDeviceInfoList(hIfDevs);
return adapterNames;
}

用于:

代码语言:javascript
复制
// Get PCI bus/slot/device/funcntion number (as 0xBBSSDDFF)
bool getPCIHWaddr(quint32 deviceIndex, ...)
{
    HDEVINFO hIfDevs;
    SP_DEVINFO_DATA infoData;    
    const GUID *netGUID = &GUID_DEVCLASS_NET;

    if (hIfDevs == INVALID_HANDLE_VALUE)
    {
        qCCritical(lcOS) << "getPCIHWaddr: Getting device class info failed with error " << GetLastError();
        return 0;
    }

    hIfDevs = SetupDiGetClassDevs(netGUID, 0, 0, DIGCF_PRESENT);

    if (hIfDevs == INVALID_HANDLE_VALUE)
    {
        qCritical() << "getPCIHWaddr: Getting device class info failed with error " << GetLastError();
        return 0;
    }

    if (!SetupDiEnumDeviceInfo(hIfDevs, deviceIndex, &infoData))
    {
        qCritical() << "getPCIHWaddr: Enumerating device information failed with error " << GetLastError();
        return 0;
    }

    // --> In failing scenario, this call returns ERROR_INVALID_DATA (13)
    if (!SetupDiGetDeviceRegistryPropertyA(hIfDevs, &infoData, SPDRP_BUSNUMBER, NULL, (LPBYTE)&devProp, sizeof(quint32), NULL))
    {
        qCritical() << "getPCIHWaddr: Query PCI bus number failed with error " << GetLastError();
        return 0;
    }

    ...
}

用于:

代码语言:javascript
复制
// Get informations on adapter by interface ID found in Registry (HKLM\SYSTEM\CurrentControlSet\Services\TcpIp\Parameter\Interfaces)
bool netIfInfo(const QString &id,...)
{
    QStringList adapterNames = adapterNames();

    /*
     * ...
     * Lot of stuff enumerating data from GetIfTable(), GetAdaptersAddresses(), until the expected deivce was found (stored QString deviceDesc)
     * ...
     */

    // --> Here it happens...
    if (!getPCIHWaddr(adapterNames.indexOf(deviceDesc), &PCIAddr, &PnPId))
    {
        ...
    }

    ...
}
EN

回答 1

Stack Overflow用户

发布于 2019-03-13 17:42:22

我认为这里的问题是getPCIHWAddr()使用了已经销毁的设备信息集的索引。我添加了一个函数,它返回指向HDEVINFO和SP_DEVINFO_DATA的指针,但不调用SetupDiDestroyDeviceInfoList(),这是在完成任务后由getPCIHWAddr()完成的-并查看:这是有效的(Win7和Win10)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55105324

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档