我正在维护一个应用程序,该应用程序使用 SetupDiGetDeviceInterfaceDetail() 来查找有关计算机上已安装串行端口的信息。我在测试时注意到有些设备(例如我的 Lucent WinModem)没有出现在该枚举中。事实证明,我公司生产的一组实现串行端口接口(interface)的设备也遇到了类似的问题。我的假设是设备的 INF 文件中缺少某些内容。有谁知道什么样的情况会导致这种遗漏?
编辑:这是我用来枚举串行端口的代码示例。我尝试了各种标志组合,但没有发现任何明显的行为差异。
DEFINE_GUID(GUID_CLASS_COMPORT, 0x4d36e978, 0xe325, 0x11ce, 0xbf, 0xc1, \
0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18);
GUID *serial_port_guid = const_cast<GUID *>(&GUID_CLASS_COMPORT);
HDEVINFO device_info = INVALID_HANDLE_VALUE;
SP_DEVICE_INTERFACE_DETAIL_DATA *detail_data = 0;
device_info = SetupDiGetClassDevs(
serial_port_guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if(device_info != INVALID_HANDLE_VALUE)
{
uint4 const detail_data_size = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + 256;
detail_data = reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA *>(new char[detail_data_size]);
SP_DEVICE_INTERFACE_DATA ifc_data;
bool more_interfaces = true;
int rcd;
memset(&ifc_data, 0, sizeof(ifc_data));
memset(detail_data, 0, detail_data_size);
ifc_data.cbSize = sizeof(ifc_data);
detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
for(uint4 index = 0; more_interfaces; ++index)
{
rcd = SetupDiEnumDeviceInterfaces(device_info, 0, serial_port_guid, index, &ifc_data);
if(rcd)
{
// we need to get the details of this device
SP_DEVINFO_DATA device_data = { sizeof(SP_DEVINFO_DATA) };
rcd = SetupDiGetDeviceInterfaceDetail(
device_info, &ifc_data, detail_data, detail_data_size, 0, &device_data);
if(rcd)
{
StrAsc device_path(detail_data->DevicePath);
byte friendly_name[256];
rcd = SetupDiGetDeviceRegistryProperty(
device_info, &device_data, SPDRP_FRIENDLYNAME, 0, friendly_name, sizeof(friendly_name), 0);
if(rcd)
{
std::for_each(
port_names.begin(),
port_names.end(),
update_friendly_name(
reinterpret_cast<char const *>(friendly_name)));
}
}
else
more_interfaces = false;
}
}
}
最佳答案
这更多是关于问题的问题。当您调用该函数时,您传入的第一个参数应该是您可能从 SetupDiGetClassDevs 中获得的 DeviceInfoSet。功能。当您调用 SetupDiGetClassDevs 函数时,您为标志指定了什么(最后一个参数)在该函数上引用 Microsoft 的页面:
DIGCF_ALLCLASSES Return a list of installed devices for all device setup classes or all device interface classes.
DIGCF_DEVICEINTERFACE Return devices that support device interfaces for the specified device interface classes. This flag must be set in the Flags parameter if the Enumerator parameter specifies a device instance ID.
DIGCF_DEFAULT Return only the device that is associated with the system default device interface, if one is set, for the specified device interface classes.
DIGCF_PRESENT Return only devices that are currently present in a system.
DIGCF_PROFILE Return only devices that are a part of the current hardware profile.
根据您的选择,设备列表会发生变化。例如,Present 标志只会显示主动插入的设备。
更新:感谢您提供示例代码。
我现在的问题是,如果您想知道调制解调器的友好名称,为什么不使用相同的调用而是指定调制解调器 Guid 而不是 COM 端口?我的调制解调器 GUID 是 4D36E96D-E325-11CE-BFC1-08002BE10318
在注册表中,我可以看到一个名为“AttachedTo”的值,它指定了一个 COM 端口。我将不得不研究在 API 中绑定(bind)到哪个属性。注册表项位于
HKLM\SYSTEM\CurrentControlSet\Control\Class{4D36E96D-E325-11CE-BFC1-08002BE10318}\
另一个更新:
仔细查看示例代码。基于此,如果您尝试获取应返回 SP_DEVICE_INTERFACE_DETAIL_DATA 的设备接口(interface)类结构。这不会提供获取设备友好名称的方法。我相信您会想要设备实例。
据我所知,设备接口(interface)用于获取可用于写入的设备路径。
我为测试您的代码所做的一件事是再次尝试磁盘设备接口(interface)。我做了一些更改以使其在我的系统上运行,但仍未完全完成。我认为一个问题(可能更多)是我需要在 SetupDiGetDeviceInterfaceDetail 调用之间调整 DevicePath 变量的大小。
void Test()
{
GUID *serial_port_guid = const_cast<GUID *>(&GUID_DEVINTERFACE_DISK);
HDEVINFO device_info = INVALID_HANDLE_VALUE;
SP_DEVICE_INTERFACE_DETAIL_DATA detail_data;
device_info = SetupDiGetClassDevs(
serial_port_guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if(device_info != INVALID_HANDLE_VALUE)
{
//uint4 const detail_data_size = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);// + 256;
//detail_data = reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA *>(new char[detail_data_size]);
SP_DEVICE_INTERFACE_DATA ifc_data;
bool more_interfaces = true;
int rcd;
memset(&ifc_data, 0, sizeof(ifc_data));
//memset(detail_data, 0, detail_data_size);
ifc_data.cbSize = sizeof(ifc_data);
detail_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
for(uint4 index = 0; more_interfaces; ++index)
{
rcd = SetupDiEnumDeviceInterfaces(device_info, 0, serial_port_guid, index, &ifc_data);
if(rcd)
{
// we need to get the details of this device
SP_DEVINFO_DATA device_data;
device_data.cbSize = sizeof(SP_DEVINFO_DATA);
DWORD intReqSize;
rcd = SetupDiGetDeviceInterfaceDetail(device_info, &ifc_data, 0, 0, &intReqSize, &device_data);
rcd = SetupDiGetDeviceInterfaceDetail(device_info, &ifc_data, &detail_data,intReqSize,&intReqSize,&device_data);
if(rcd)
{
//StrAsc device_path(detail_data->DevicePath);
byte friendly_name[256];
rcd = SetupDiGetDeviceRegistryProperty(
device_info, &device_data, SPDRP_FRIENDLYNAME, 0, friendly_name, sizeof(friendly_name), reinterpret_cast<DWORD *>(sizeof(friendly_name)));
if(rcd)
{
cout<<reinterpret_cast<char const *>(friendly_name);
}
else
{ int num = GetLastError();
}
}
else
{
int num = GetLastError();
}
}
else
more_interfaces = false;
}
}
SetupDiDestroyDeviceInfoList(device_info);
}
此外,在 INF 中,您可能必须添加 AddInterface指令将您的驱动程序与正确的接口(interface)相关联。
关于c++ - 为什么某些设备不使用 SetupDiGetDeviceInterfaceDetail() 进行枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/571229/