使用C WRL打开UsbDevice – ERROR_INVALID_HANDLE

我正在尝试获取一个 Windows :: Devices :: Usb :: UsbDevice对象,引用我拥有的特定USB设备,以便将其传递给第三方插件.由于项目限制,我无法使用C/C++X扩展.

在查看了无数的线程,答案和引用之后,我想出了一个初始实现,它可以在我需要的WinRT类上调用静态方法.唯一的问题是,即使没有调用导致HRESULT失败,最后一次调用FromIdAsync也不起作用,因为GetLastError()而给我ERROR_INVALID_HANDLE(6).

简单地读取错误名称会让我误认为是获取设备的ID,因为这是我传递该调用的唯一句柄,但我尝试传递一个常量字符串(我知道这是正确的)并且它产生了相同的结果.

这就是我调用FromIdAsync *的方式:

// Retrieves static methods for UsbDevice class
ComPtr<IUsbDeviceStatics> usbDevSt;
hr = GetActivationFactory(
    HStringReference(RuntimeClass_Windows_Devices_Usb_UsbDevice).Get(),&usbDevSt
);

// Creates an event to work as a 'semaphore',for waiting for the 'FromIdAsync'
// call to be completed
Event openEvent(CreateEventEx(
    nullptr,nullptr,CREATE_EVENT_MANUAL_RESET,WRITE_OWNER | EVENT_ALL_ACCESS
));
if (!openEvent.IsValid()) return nullptr;

// Setups a callback for when the device enumeration is done
auto asyncopenCb = Callback<IAsyncoperationCompletedHandler<UsbDevice*>>(
    [&openEvent](IAsyncoperation<UsbDevice*> *opHandler,AsyncStatus status) -> HRESULT {
        if (!opHandler || status != AsyncStatus::Completed) {
            DWORD x = GetLastError(); // ERROR_INVALID_HANDLE (6)
        }

        SetEvent(openEvent.Get());
        return S_OK;
    }
);

// Invokes the 'asyncopenop' method,equivalent to UsbDevice::FromIdAsync(String)
ComPtr<IAsyncoperation<UsbDevice*>> asyncopenop;
hr = usbDevSt->FromIdAsync(
    devId.Get(),asyncopenop.GetAddressOf()
);

// Registers completed callback
hr = asyncopenop->put_Completed(asyncopenCb.Get());

// Waits for open operation to complete before continuing
WaitForSingleObjectEx(openEvent.Get(),INFINITE,false);

// Retrieves the result from the asynchronous call
ComPtr<IUsbDevice> dev;
hr = asyncopenop->GetResults(dev.GetAddressOf());

这就是我得到devId *的方式:

// Retrieve static methods for Deviceinformation class
ComPtr<IDeviceinformationStatics> devInfoSt;
HRESULT hr = GetActivationFactory(
    HStringReference(RuntimeClass_Windows_Devices_Enumeration_Deviceinformation).Get(),&devInfoSt
);

// Create an event to work as a 'semaphore',for waiting for the 'FindAllAsyncAqsFilter' call to be completed
Event findEvent(CreateEventEx(
    nullptr,WRITE_OWNER | EVENT_ALL_ACCESS
));
if (!findEvent.IsValid()) return nullptr;

// Setup a callback for when the device enumeration is done
auto asyncFindCb = Callback<IAsyncoperationCompletedHandler<DeviceinformationCollection*>>(
    [&findEvent](IAsyncoperation<DeviceinformationCollection*> *opHandler,AsyncStatus status) -> HRESULT {
        SetEvent(findEvent.Get());
        return S_OK;
    }
);

// Invoke the 'FindAllAsyncAqsFilter' method,equivalent to Deviceinformation::FindAllAsync(String)
ComPtr<IAsyncoperation<DeviceinformationCollection*>> asyncFindOp;
hr = devInfoSt->FindAllAsyncAqsFilter(
    HStringReference(DEVICE_FILTER).Get(),asyncFindOp.GetAddressOf()
);

// Registers completed callback
hr = asyncFindOp->put_Completed(asyncFindCb.Get());

// Waits for enumeration to complete before continuing
WaitForSingleObjectEx(findEvent.Get(),FALSE);

// Retrieves the result from the asynchronous call
ComPtr<IVectorView<Deviceinformation*>> devColl;
hr = asyncFindOp->GetResults(devColl.GetAddressOf());

// Checks for collection size
unsigned int collSize;
hr = devColl->get_Size(&collSize);

if (collSize == 0) {
    return nullptr;
}

// Retrieves the first Deviceinformation object from the collection
ComPtr<IDeviceinformation> devInfo;
hr = devColl->GetAt(0,devInfo.GetAddressOf());

// Retrieves the device's id
HString devId;
hr = devInfo->get_Id(devId.GetAddressOf());

另外,我这样做初始化WinRT:

RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
if (Failed(initialize)) return nullptr;

*多个if(Failed(hr))返回nullptr;为简洁而删除.

解决方法

GetLastError函数

Retrieves the calling thread’s last-error code value.
The last-error code is maintained on a per-thread basis.
Multiple threads do not overwrite each other’s last-error code.

but I tried passing a constant string instead (which I knew was correct) and it yielded the same results.

ERROR_INVALID_HANDLE
调用者在InterfaceHandle参数中传递NULL.

如上所述,您必须从HRESULT获得结果

[&openEvent](IAsyncoperation<UsbDevice*> *opHandler,AsyncStatus status) -> HRESULT

我会尝试循环集合以找出如何从中获取错误

https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.enumeration.deviceinformationcollection.indexof

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...