C++ 什么会导致SetupDiGetClassDevs不返回设备接口?(Windows,C+;+;)

C++ 什么会导致SetupDiGetClassDevs不返回设备接口?(Windows,C+;+;),c++,windows,unity3d,usb,hid,C++,Windows,Unity3d,Usb,Hid,我研究这个问题已经一个多月了 我想做什么: 获取连接到系统且未发生故障的HID设备列表 发生了什么: SetupDiGetClassDevs间歇性地不返回任何设备(当针对HID设备进行筛选时),但仅针对所讨论的特定进程。同时运行相同调用的其他进程可以完美地工作。无论我如何努力,我都无法在一个干净的项目中重现这个问题 背景: 我是一个在Unity 3D(游戏引擎)下运行的输入系统的作者。我的一个客户在他的(巨大的)项目中遇到了操纵杆热插拔的问题。在他的游戏的标题屏幕上,一切都很顺利。加载第一个游戏

我研究这个问题已经一个多月了

我想做什么: 获取连接到系统且未发生故障的HID设备列表

发生了什么: SetupDiGetClassDevs间歇性地不返回任何设备(当针对HID设备进行筛选时),但仅针对所讨论的特定进程。同时运行相同调用的其他进程可以完美地工作。无论我如何努力,我都无法在一个干净的项目中重现这个问题

背景: 我是一个在Unity 3D(游戏引擎)下运行的输入系统的作者。我的一个客户在他的(巨大的)项目中遇到了操纵杆热插拔的问题。在他的游戏的标题屏幕上,一切都很顺利。加载第一个游戏关卡后,Windows会间歇性(看似随机)报告零HID设备。只要当前控制器仍然连接,输入工作正常,但在这些“故障”期间,如果控制器被卸下并重新插入,Windows将返回0个设备接口

我无法访问该客户的项目(超过80GB),但已将我自己的测试代码注入可执行文件中,以试图找到问题的根源。我有一千多个客户,只有这个项目似乎有这个问题

这里是我在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);