Слово перед: большая часть текста и кода следует, но я пытаюсь объяснить мою проблему (которая происходит случайно) как можно более подробно:
Мое приложение, которое работает с сетевыми интерфейсами черезthet API установки, происходит сбой случайно, наиболее вероятно при попытке использовать SetupDiGetDeviceRegistryProperty () .Основная проблема, с которой я столкнулся, заключается в том, что список устройств, возвращаемых SetupDiEnumDeviceInfo () (я использую его для получения индекса определенного сетевого адаптера, который будет передан SetupDiGetDeviceRegistryProperty () )изменяется "неожиданным" образом.Моя первая проблема заключалась в том, что устройства появляются и / или исчезают из этого списка.Как указано здесь , первое, что я обнаружил, что использование
const GUID *netGUID = &GUID_DEVCLASS_NET;
SetupDiGetClassDevs(netGUID, 0, 0, DIGCF_PROFILE)
вместо
const GUID *netGUID = &GUID_DEVCLASS_NET;
SetupDiGetClassDevs(netGUID, 0, 0, DIGCF_PRESENT)
всегда возвращает все сетевые адаптеры, которые можно увидеть на устройствеменеджер (в том числе «скрытый» = «не установленный»).Это сработало так, как и ожидалось - с Windows 10 (64-разрядная версия).
Убедившись, что это сработало, я скомпилировал приложение для использования с 32-разрядной ОС Windows 7 и протестировал его.К сожалению, я должен видеть, что проблема все еще существует - SetupDiEnumDeviceInfo () по-прежнему возвращает все сетевые адаптеры, как и ожидалось, но порядок совсем не тот и (а) последующие вызовы, если SetupDiGetDeviceRegistryProperty () ошибка с ERROR_INVALID_DATA .В большинстве случаев я получаю
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)
, но иногда порядок меняется следующим образом:
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) может привести к тому, что определенный мной индекс не будет соответствоватьНамеренное устройство больше.Есть ли способ предотвратить изменение порядка в списке устройств или я что-то не так делаю?
// 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;
}
Используется:
// 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;
}
...
}
Используется:
// 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))
{
...
}
...
}