我正在尝试获取一个
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;
解决方法
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