Visual Open UsbDevice с использованием C ++ WRL — ERROR_INVALID_HANDLE

Я пытаюсь получить Windows::Devices::Usb::UsbDevice объект, ссылающийся на конкретное USB-устройство, которое я имею, чтобы передать его стороннему плагину. Из-за ограничений проекта я не могу использовать C++/CX расширение.

Посмотрев на бесчисленные потоки, ответы и ссылки, я придумал начальную реализацию, которая делает некоторую чёрную магию для вызова статических методов в нужных мне классах WinRT. Единственная проблема заключается в том, что, хотя ни один вызов не приводит к провалу HRESULT, последний звонок FromIdAsync не работает, давая мне ERROR_INVALID_HANDLE (6) как результат GetLastError(),

Простое чтение имени ошибки делает меня ошибкой в ​​получении идентификатора устройства, поскольку это единственный дескриптор, который я передаю при вызове, но вместо этого я попытался передать константную строку (что, как я знал, было правильно), и это дало те же результаты.

Вот как я призываю 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,
nullptr,
CREATE_EVENT_MANUAL_RESET,
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(), INFINITE, 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;

* Multiple if (FAILED(hr)) return nullptr; удалено для краткости.

7

Решение

GetLastError function

Получает значение кода последней ошибки вызывающего потока.
Код последней ошибки поддерживается для каждого потока.
Несколько потоков не перезаписывают код последней ошибки друг друга.


но вместо этого я попытался передать постоянную строку (что, как я знал, было правильно), и это дало те же результаты.

ERROR_INVALID_HANDLE
Вызывающая сторона передала NULL в параметре InterfaceHandle.

Как уже упоминалось выше, вы должны получить результат от HRESULT

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

Я бы попытался перебрать коллекцию, чтобы выяснить, как получить ошибку от

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

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]