C++ 什么会导致SetupDiGetClassDevs不返回设备接口?(Windows,C+;+;)
我研究这个问题已经一个多月了 我想做什么: 获取连接到系统且未发生故障的HID设备列表 发生了什么: SetupDiGetClassDevs间歇性地不返回任何设备(当针对HID设备进行筛选时),但仅针对所讨论的特定进程。同时运行相同调用的其他进程可以完美地工作。无论我如何努力,我都无法在一个干净的项目中重现这个问题 背景: 我是一个在Unity 3D(游戏引擎)下运行的输入系统的作者。我的一个客户在他的(巨大的)项目中遇到了操纵杆热插拔的问题。在他的游戏的标题屏幕上,一切都很顺利。加载第一个游戏关卡后,Windows会间歇性(看似随机)报告零HID设备。只要当前控制器仍然连接,输入工作正常,但在这些“故障”期间,如果控制器被卸下并重新插入,Windows将返回0个设备接口 我无法访问该客户的项目(超过80GB),但已将我自己的测试代码注入可执行文件中,以试图找到问题的根源。我有一千多个客户,只有这个项目似乎有这个问题C++ 什么会导致SetupDiGetClassDevs不返回设备接口?(Windows,C+;+;),c++,windows,unity3d,usb,hid,C++,Windows,Unity3d,Usb,Hid,我研究这个问题已经一个多月了 我想做什么: 获取连接到系统且未发生故障的HID设备列表 发生了什么: SetupDiGetClassDevs间歇性地不返回任何设备(当针对HID设备进行筛选时),但仅针对所讨论的特定进程。同时运行相同调用的其他进程可以完美地工作。无论我如何努力,我都无法在一个干净的项目中重现这个问题 背景: 我是一个在Unity 3D(游戏引擎)下运行的输入系统的作者。我的一个客户在他的(巨大的)项目中遇到了操纵杆热插拔的问题。在他的游戏的标题屏幕上,一切都很顺利。加载第一个游戏
这里是我在C++ DLL中使用的一些测试代码,查询系统中的HID设备的数量。
int EnumerateDevices() {
int deviceCount = 0;
LPGUID guid = (LPGUID)malloc(sizeof(GUID));
HidD_GetHidGuid(guid);
HDEVINFO deviceInfoSet = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (deviceInfoSet != INVALID_HANDLE_VALUE) {
SP_DEVINFO_DATA* deviceInfoData = new SP_DEVINFO_DATA();
deviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
deviceInfoData->DevInst = 0;
DWORD deviceIndex = 0;
int totalDeviceCount = 0;
int totalInterfaceCount = 0;
while (SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex, deviceInfoData)) {
deviceIndex += 1;
SP_DEVICE_INTERFACE_DATA* deviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
deviceInterfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
int deviceInterfaceIndex = 0;
while (SetupDiEnumDeviceInterfaces(deviceInfoSet, deviceInfoData, guid, deviceInterfaceIndex, deviceInterfaceData)) {
deviceInterfaceIndex++;
deviceCount++;
totalInterfaceCount++;
}
totalDeviceCount++;
}
stringstream ssss;
if(deviceIndex == 0) {
ssss << "No devices. Last error = " << GetLastError() << "/n";
}
ssss << "Total Device Count = " << totalDeviceCount << " Total Interface Count = " << totalInterfaceCount;
Log(ssss.str());
SetupDiDestroyDeviceInfoList(deviceInfoSet);
delete(deviceInfoData);
} else {
stringstream sss;
sss << "Invalid handle value!";
Log(sss.str());
}
free(guid);
return deviceCount;
我总是得到一个有效的结果返回——168。这一点从未改变。但是,这些都不是设备接口,所以我不能使用这些信息。如果我重新添加设备接口过滤器,我会间歇性地得到0。同样,只有在加载了大关卡且游戏内存占用超过2GB时,才会发生这种情况。我读过一些关于直接输入和堆内存不足的问题,导致它返回OK结果,但没有设备,但据我所知,内存和这个问题之间没有关系(除此之外,当内存为~500MB时,它不会出现在标题屏幕上,只有当级别加载超过1.6GB左右时,您才会开始看到它——但同样,我无法访问该项目以确定是否是其中的某个插件/组件导致了这一点。)
只是想重申一下:
如果我运行一个并行进程(Unity的另一个实例使用不同的项目)同时查看日志,我始终在该进程返回0的同一时刻收到6个设备的正确值。这种行为与Windows HID函数、直接输入和XInput一致。当其中一个出现故障时,所有设备都会出现故障。但同时运行的其他进程每次查看所有设备都不会出现问题拉姆
Unity是基于Mono的一个古老版本,所以我想可能会有问题,但是我试图通过旋转一个本机线程来进行测试来绕过Mono的问题,结果表明这并没有什么区别
在这方面工作了这么长时间后,我在网上搜寻信息,但找不到任何与这个问题有点类似的东西
编辑:忘了提到,这个项目也使用Steam。修复方法是,如果您的程序在64位操作系统上运行,则通过将可丢弃堆分配到0x8000000以上,强制MS代码分配到0x8000000以下的内存
HDEVINFO deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);