【发布时间】:2023-04-04 20:19:01
【问题描述】:
我正在使用一些遗留代码来枚举我机器上的端口:
#include <windows.h>
#include <devguid.h>
#include <setupapi.h>
#include <string>
#include <iostream>
#include <assert.h>
bool GetTextProperty( std::string& sProperty,
HDEVINFO dev,
_SP_DEVINFO_DATA* pDeviceInfoData,
DWORD prop )
{
char szBuf[MAX_PATH];
DWORD iPropertySize = 0;
if (SetupDiGetDeviceRegistryProperty(dev, pDeviceInfoData,
prop, 0L, (PBYTE) szBuf, MAX_PATH, &iPropertySize))
{
sProperty = szBuf;
assert( iPropertySize >= sProperty.size() + 1 );
return true;
}
return false;
}
inline bool readRegistryKeyValue( HKEY hKey, const std::string& key, std::string& value )
{
bool res = false;
CHAR szBuffer[512];
DWORD dwBufferSize = sizeof(szBuffer);
ULONG nError = RegQueryValueEx(hKey, key.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
if (ERROR_SUCCESS == nError)
{
value = szBuffer;
res = true;
}
return res;
}
void ListPorts()
{
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
DWORD i;
hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 0L, 0L, DIGCF_PRESENT);
if ( hDevInfo == INVALID_HANDLE_VALUE )
{
//Medoc_ReportError(MEDOC_ERROR_HARDWARE_DRIVER_API_FAILED,
// &hDevInfo, sizeof hDevInfo);
assert( false );
}
else
{
// Enumerate through all devices in Set.
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData) != 0; i++)
{
char szBuf[MAX_PATH];
short wImageIdx = 0;
short wItem = 0;
DWORD iPropertySize;
if (SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData,
SPDRP_FRIENDLYNAME, 0L, (PBYTE) szBuf, MAX_PATH, &iPropertySize))
{
std::cout << "Smart name: " << szBuf << std::endl;
HKEY hKey = SetupDiOpenDevRegKey(
hDevInfo,
&DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DEV,
KEY_READ );
if ( hKey )
{
std::string portName;
readRegistryKeyValue( hKey, "PortName", portName );
std::cout << "Port name: " << szBuf << std::endl;
for ( DWORD prop = 0; prop != SPDRP_MAXIMUM_PROPERTY; ++prop )
{
std::string temp;
GetTextProperty( temp, hDevInfo, &DeviceInfoData, prop );
std::cout << prop << " : " << temp << std::endl;
}
RegCloseKey(hKey);
}
}
}
}
// Cleanup
SetupDiDestroyDeviceInfoList(hDevInfo);
}
int main( int argc, char* argv[] )
{
ListPorts();
return 0;
}
除其他信息外,这让我可以访问端口名称 (COM*)、类型(例如 FTDI)、VID 和 PID...
但是,当我插入许多基于 FTDI 芯片的不同设备时,它们都具有相同的信息(SPDRP_HARDWAREID prperty 报告FTDIBUS\COMPORT&VID_0403&PID_6015 或FTDIBUS\COMPORT&VID_0403&PID_6010)。所以我分不清谁是谁。
当我使用 USB 嗅探器(“Device Monitoring Studio”)时,它能够报告更多相关信息,而无需与端口建立任何连接:
是否可以通过 Windows API 访问这种扩展信息,以通过名称区分使用相同 FTDI 芯片的许多设备?还是我必须使用 FTDI 驱动程序 API 来实现这一点?
【问题讨论】:
-
您在屏幕截图中显示的内容是否与来自
SPDRP_FRIENDLYNAME的结果不匹配?也许从父级而不是从虚拟 COM 端口本身获取友好名称?但它仍然不会是独一无二的,正如您的屏幕截图所示...... -
GUID_DEVCLASS_PORTS 将为您提供 LPT1、COM1 等。如果您需要 USB 控制器,您可以使用 GUID_DEVCLASS_USB。
-
@BenVoigt:
SPDRP_FRIENDLYNAME给了我USB Serial Port (COM12)这不是那么友好;-)。我不是在寻找唯一的名称,而是比“FTDI”更多的信息。 “父母”是什么意思? -
@SimonMourier:当使用
GUID_DEVCLASS_USB时,我只有一个设备 (USBXHCI),而我连接了 3 个设备。所以这无济于事。 -
是的,因为您的循环在不使用 GUID_DEVCLASS_PORTS 时退出得太早,我已经修改了您的程序(并且也更改为 unicode):pastebin.com/raw/UzbWS07D,它似乎可以工作。
标签: c++ windows winapi usb ftdi