Search code examples
c#usb

FileStream.Dispose throws UnauthorizedAccessException how to handle disposing?


The FileStream is created from SafeHandle that points directly to USB Printing Support driver, so it is not a regular FileStream.

Now I am trying to fix a problem when a user unplugs and re-plugs the USB device. A new handle is created and the old one now points somewhere else. I need to reinitialize the connection, but before creating a new one my instinct is to Dispose the old resources

Dispose everything that is disposable

Trying to dispose this FileStream I get UnauthorizedAccessException with regular message Access to the path is denied. Do I just wrap my Dispose calls in method Disconnect to try/catch and leave them undisposed as is? Maybe there is a better way for USB I/O than FileStream?

Here is some code:

public void Connect()
{
    Disconnect();
    _printerHandle = UsbPrinterResolver.OpenUSBPrinter(ConnectionString);
    _printerStream = new FileStream(_printerHandle, FileAccess.ReadWrite);
}
protected void Disconnect()
{
    _printerStream?.Dispose(); // only works when the usb connection is working and valid
    _printerHandle?.Dispose();
    _printerStream = null;
    _printerHandle = null;
}

The UsbPrinterResolver is actually the one from question Figuring which printer name corresponds to which device ID I just modified the //FIXME part. But the resolved handles seemed to work great.


Solution

  • FileStream internally flushes the stream before disposing.

    So you just need to catch the exception on the outside of whatever is disposing this object.

    As far as disposing the handle: it will be closed regardless, you don't need to dispose that because the stream "owns" the handle. See the source code here. So you don't need to keep it around.

    public void Connect()
    {
        Disconnect();
        var printerHandle = UsbPrinterResolver.OpenUSBPrinter(ConnectionString);
        try
        {
            _printerStream = new FileStream(_printerHandle, FileAccess.ReadWrite);
        }
        catch
        {
            printerHandle.Dispose();  // need to dispose the handle if FileStream ctor fails
            throw;
        }
    }
    
    protected void Disconnect()
    {
        _printerStream?.Dispose();
        _printerStream = null;
    }