You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

USB打印机场景下FileStream.Dispose抛UnauthorizedAccessException的处理

USB打印设备Dispose异常处理及替代方案

一、用try/catch包裹Dispose调用的可行性

完全可以这么做,但要注意只捕获特定的UnauthorizedAccessException,别笼统捕获所有异常,避免掩盖其他潜在问题。修改后的Disconnect方法如下:

protected void Disconnect()
{
    if (_printerStream != null)
    {
        try
        {
            _printerStream.Dispose();
        }
        catch (UnauthorizedAccessException)
        {
            // 设备已断开,该异常属于预期情况,直接忽略
        }
        finally
        {
            _printerStream = null;
        }
    }

    _printerHandle?.Dispose();
    _printerHandle = null;
}

设备插拔后旧句柄失效,FileStream.Dispose内部会尝试执行文件系统相关的清理操作,这些操作在无效句柄下会触发权限异常,捕获该特定异常即可,不会影响后续的句柄释放和资源清理。

二、更优的USB I/O实现方式

FileStream本质是为文件系统设计的封装,用来适配USB打印设备句柄确实存在兼容性问题,更推荐以下两种方案:

1. 直接基于SafeHandle调用Win32 API

跳过FileStream的封装,直接用ReadFile/WriteFile等Win32 API读写数据,释放资源时直接调用SafeHandle的Dispose(内部会调用CloseHandle,这是USB设备句柄的标准释放方式),完全避免FileStream带来的异常。

示例代码框架:

using System.ComponentModel;
using System.Runtime.InteropServices;

// 导入Win32 API
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile(SafeHandle hFile, byte[] lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped);

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteFile(SafeHandle hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, IntPtr lpOverlapped);

private SafeHandle _printerHandle;

public void Connect()
{
    Disconnect();
    _printerHandle = UsbPrinterResolver.OpenUSBPrinter(ConnectionString);
}

protected void Disconnect()
{
    _printerHandle?.Dispose();
    _printerHandle = null;
}

// 读数据示例
public int ReadPrinterData(byte[] buffer)
{
    if (_printerHandle == null || _printerHandle.IsInvalid)
        throw new InvalidOperationException("打印机未连接");
    
    if (ReadFile(_printerHandle, buffer, (uint)buffer.Length, out uint bytesRead, IntPtr.Zero))
        return (int)bytesRead;
    
    throw new Win32Exception(Marshal.GetLastWin32Error());
}

// 写数据示例
public void WritePrinterData(byte[] data)
{
    if (_printerHandle == null || _printerHandle.IsInvalid)
        throw new InvalidOperationException("打印机未连接");
    
    if (!WriteFile(_printerHandle, data, (uint)data.Length, out _, IntPtr.Zero))
        throw new Win32Exception(Marshal.GetLastWin32Error());
}

2. 使用专门的USB通信库

比如LibUsbDotNet这类针对USB设备开发的专用库,它对USB设备的连接、断开、读写操作都做了针对性优化,比手动调用Win32 API更便捷,也能更好处理设备插拔后的状态变化,稳定性更高。

内容的提问来源于stack exchange,提问作者Ernis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:05:22