Mel*_*per 6 c# usb winusb safefilehandle
我试图用CloseHandle释放USB接口的句柄.我得到的例外是:
System.Runtime.InteropServices.SEHException(0x80004005):外部组件引发了异常.位于Usb.Net.Windows.UsbInterface.Dispose()的Device.Net.APICalls.CloseHandle(SafeFileHandle hObject)位于C:\ GitRepos\Device.Net\src\Usb.Net\Windows\UsbInterface.cs:
位于Usb的第23行C:\ GitRepos\Device.Net\src\Usb.Net\Windows\WindowsUsbDevice.cs中的.Net.Windows.WindowsUsbDevice.Dispose():第131行
我试图在我班级的Dispose方法中这样做.
编辑背景:我试图这样做的原因是我的代码在第二次运行时崩溃了.根据这篇文章,我必须在我使用CreateFile创建的设备的句柄上调用CloseHandle.无论如何,这都是在我的代码中完成的,因为设备的句柄因为是SafeFileHandle而被处理掉了.但是,有人告诉我,我需要在接口的句柄上调用CloseHandle.我不知道这是不是真的.我试图这样做,以排除不调用CloseHandle是错误的原因的可能性.基于其他评论和研究,我现在认为这是一个错误,并且调用WinUsb_Free就足够了.它是否正确?
Hans Passant的回答告诉我要删除对CloseHandle的调用,但正如我在评论中指出的那样,原始代码(在master中)从未调用过CloseHandle.当然,删除电话会有效,但这不是问题.下面的问题是:使用WinUSB API释放USB接口的过程是什么?.它只是简单地调用WinUsb_Free?这就是我所拥有的所有信息都让我相信.
这是我提出这个问题之前的原始处置方法.它没有调用CloseHandle.
public void Dispose()
{
if (_IsDisposed) return;
_IsDisposed = true;
var isSuccess = WinUsbApiCalls.WinUsb_Free(Handle);
WindowsDeviceBase.HandleError(isSuccess, "Interface could not be disposed");
}
Run Code Online (Sandbox Code Playgroud)
来自WindowsUsbInterface(https://github.com/MelbourneDeveloper/Device.Net/blob/9ebc122a2755dda2824c6eda961d092f2f6e83b5/src/Usb.Net/Windows/WindowsUsbDevice.cs#L122):
public override void Dispose()
{
if (_IsDisposing) return;
_IsDisposing = true;
try
{
foreach (var usbInterface in _UsbInterfaces)
{
usbInterface.Dispose();
}
_UsbInterfaces.Clear();
_DeviceHandle?.Dispose();
_DeviceHandle = null;
base.Dispose();
}
catch (Exception ex)
{
Logger.Log("Error disposing of device", ex, nameof(WindowsUsbDevice));
}
_IsDisposing = false;
}
Run Code Online (Sandbox Code Playgroud)
来自UsbInterface(https://github.com/MelbourneDeveloper/Device.Net/blob/9ebc122a2755dda2824c6eda961d092f2f6e83b5/src/Usb.Net/Windows/UsbInterface.cs#L18):
public void Dispose()
{
var isSuccess = WinUsbApiCalls.WinUsb_Free(Handle);
WindowsDeviceBase.HandleError(isSuccess, "Interface could not be disposed");
isSuccess = APICalls.CloseHandle(Handle);
WindowsDeviceBase.HandleError(isSuccess, "Interface could not be disposed");
}
Run Code Online (Sandbox Code Playgroud)
API调用定义(https://github.com/MelbourneDeveloper/Device.Net/blob/CloseHandle/src/Device.Net/Windows/APICalls.cs):
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(SafeFileHandle hObject);
Run Code Online (Sandbox Code Playgroud)
我也试过简单地处理句柄,因为它是一个SafeFileHandle,但SafeFileHandle的Dispose方法给了我相同的错误信息.这告诉我SafeFileHandle的Dispose方法也可能调用CloseHandle,同样的问题正在发生.
其他人提到我应该使用IntPtr而不是SafeFileHandle.所以,我尝试在CloseHandle接口上使用IntPtr,但问题是一样的:

这是WinUsb_Initialize的定义
[DllImport("winusb.dll", SetLastError = true)]
public static extern bool WinUsb_Initialize(SafeFileHandle DeviceHandle, out IntPtr InterfaceHandle);
Run Code Online (Sandbox Code Playgroud)
使用WinUSB API释放USB接口的过程是什么?在C#中我是否需要做些不同的事情?为什么会出现这个错误?
Han*_*ant 10
当句柄不是正确的kernel32句柄或句柄已经关闭时,CloseHandle()失败.通过github源代码,我发现了问题的起源:
[DllImport("winusb.dll", SetLastError = true)]
public static extern bool WinUsb_Initialize(SafeFileHandle DeviceHandle,
out SafeFileHandle InterfaceHandle);
Run Code Online (Sandbox Code Playgroud)
编辑以适应并使问题更加明显.第二个参数的类型不正确,该函数不返回kernel32句柄,因此将其包装在SafeFileHandle中是不正确的.这是一个不透明的句柄,本机api声明中的WINUSB_INTERFACE_HANDLE,通常是引擎盖下的指针.只有一种正确的方法可以关闭它,你必须调用WinUsb_Free().该代码这样做,但也呼吁CloseHandle的是不正确的,也是注定要失败的.SafeFileHandle提供的CloseHandle()调用同样会失败,你可能还没有那么远.
将参数类型更改为IntPtr.这需要对其他几个代码进行更改,主要是在UsbInterface类中.同样将其Handle属性类型更改为IntPtr.在Dispose()方法中删除CloseHandle()调用.编写自己的SafeHandle派生类来包装它是另一种方法,然后重写ReleaseHandle()来调用WinUsb_Free().
我认为这个问题的答案是没有必要在USB接口上调用CloseHandle。根据本页顶部的 Dispose 方法,调用 WinUsb_Free 应该足以释放接口。只需调用 CloseHandle 即可释放由 CreateFile 创建的设备的句柄。
public void Dispose()
{
if (_IsDisposed) return;
_IsDisposed = true;
var isSuccess = WinUsbApiCalls.WinUsb_Free(Handle);
WindowsDeviceBase.HandleError(isSuccess, "Interface could not be disposed");
}
Run Code Online (Sandbox Code Playgroud)
这篇文章对此说得非常清楚。
- CloseHandle 以释放 CreateFile 创建的句柄,如步骤 1 中所述。
- WinUsb_Free 释放设备的 WinUSB 接口句柄,该句柄由 WinUsb_Initialize 返回。
汉斯·帕桑特还推荐:
删除其 Dispose() 方法中的 CloseHandle() 调用
另外,来自汉斯·帕桑:
第二个参数的类型不正确,该函数不返回 kernel32 句柄,因此将其包装在 SafeFileHandle 中是不正确的。这是一个不透明的句柄,是本机 api 声明中的 WINUSB_INTERFACE_HANDLE,通常是一个隐藏的指针。只有一种正确的方法可以关闭它,您必须调用WinUsb_Free()。
这并不直接涉及我所问的问题,但这是一个公平的观点。正如 Hans 指出的那样,我无法在从 WinUsb_Initialize 返回的句柄上调用 Dispose() 的原因是,这样做会在后台调用 CloseHandle,而 WinUsb_Initialize 返回的第二个参数不是 kernel32 句柄,因此 CloseHandle() 会赢。无论如何都行不通。这只是导致似乎没有任何迹象表明有必要在接口上调用 CloseHandle。所以,我相信我遇到的问题(单独的问题)与不调用 CloseHandle 无关。看来是固件本身的问题,厂家似乎已经确认了这一点。更多细节即将到来。
注意:如果我错了,请告诉我为什么错了,并给我指出一个使用 CloseHandle 关闭 USB 接口上的句柄的示例。
| 归档时间: |
|
| 查看次数: |
322 次 |
| 最近记录: |