首页 文章

释放未插入的虚拟串行端口

提问于
浏览
9

我的USB条形码扫描仪有点问题 . 我正在使用带有“SerialPort”类的Scanner:

this._barcodeScanner = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One) { Handshake = Handshake.None, ReadTimeout = 500, WriteTimeout = 500 };
        this._barcodeScanner.Open();
        this._barcodeScanner.DataReceived += BarcodeScannerCallback;

如果我通过“SerialPort”类打开USB设备,我就无法正常关闭软件,虚拟端口永远保持打开状态,或直到我重启整个计算机 .

所以我的问题是,在我通过C#代码拔出设备后,有没有办法关闭虚拟端口?

问候

[编辑#1]

好的,还有一些代码:

这样,如果设备已插入,我每隔10秒检查一次:

private bool CheckUsbDeviceAvailability()
    {
        ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\WMI",
        "SELECT * FROM MSSerial_PortName WHERE PortName = '" + this.PortName + "'");

        if (searcher.Get().Count > 0)
            return true;
        return false;
    }

那是串口的Callback-Event:

void BarcodeScannerCallback(object sender, SerialDataReceivedEventArgs e)
    {
        Thread.Sleep(500);
        string data = this._barcodeScanner.ReadExisting().Replace(Convert.ToChar(2), Convert.ToChar(32)).Trim();
        if (data.StartsWith("AX"))
        {
            string[] arrData = data.Split('\n');
            this._barcodeScanner.StopAvailabilityThread();
            Barcode code = new Barcode(arrData[0].Replace("\r", ""));

            if (CheckIfBarcodeExists(code))
                this.UpdateBarcodeNode(code);
            else
                this.CreateBarcodeNode(code);

            BarcodeScannerCallbackEvent(sender, e, code);
            this._barcodeScanner.StartAvailabilityThread();
        }

        this._barcodeScanner.ComDevicePluggedIn = ScannerDevice.ComAvailabilityState.Available;
    }

如果它不再回答它将触发“DeviceNotAvailableEvent()”:

void BarcodeScannerDeviceNotAvailableEvent()
    {
        this._barcodeScanner.Close();
        this._barcodeScanner.Dispose();
    }

我已经覆盖了“SerialPort”类的Dispose事件,以便它将中止Thread:

protected override void Dispose(bool isDisposing)
    {
        if (isDisposing)
        {
            this._deviceAvailableThread.Abort();

        }

        base.Dispose(isDisposing);
    }

2 回答

  • 0

    这个问题存在于.Net 2,3,3.5中你可以使用框架4(.net 4中不存在问题)

  • 23

    串行端口可以追溯到计算的石器时代 . 这就是你插入ASR-33电传打字机开始输入你的Fortran程序的地方 . 电气接口非常简单 . Windows API也是使用您自己的代码中的串行端口 . 几乎任何运行时环境都支持它们 .

    USB完全取代了串口硬件 . 它具有更高级的机器逻辑接口,支持许多不同类型的设备 . 它支持即插即用,允许操作系统检测设备何时连接或移除,以及自动安装设备驱动程序等 .

    然而,这种灵活性是有代价的,USB设备总是需要设备驱动程序才能使用 . 设备驱动程序不是平等的 . 不同的驱动程序需要不同的方式来与设备通信 . 通常通过DeviceIoControl()或Read / WriteFile()完成,但这些是非常不透明的API函数 . 在USB的早期,设备制造商将提供一个DLL,它提供了丰富的API来隐藏实现细节 .

    这不是很好,制造商不擅长编写好的API,他们肯定不喜欢支持它们 . 因此,一个好的解决方案是支持标准API,可以在任何机器上使用,由任何运行时支持,由其他人记录和维护 . 像串口API一样 .

    这不是很好,制造商不擅长编写模拟串行端口的设备驱动程序 . API的最大障碍是它没有逻辑接口来支持它 . 有一些支持用于检测设备是通过DTR硬件握手线连接的,但是没有任何支持来检测端口不再存在 .

    拆卸USB设备是个问题 . 在理想情况下,设备驱动程序中内置的仿真器只会假装串口仍在那里,直到设备上的最后一个句柄关闭 . 这将是逻辑实现,因为没有办法触发即插即用事件 . 由于某些奇怪的原因,似乎很难实现 . 大多数USB驱动程序采用简洁的快捷方式,它们只是使设备即使在使用时也会消失 .

    这会对使用该设备的任何用户模式代码造成严重破坏 . 这通常被写为假设它是一个真正的串行端口,真正的串行端口不会突然消失 . 至少没有画出明亮的蓝色火花 . 出了什么问题是非常不可预测的,因为它取决于驱动程序如何响应不再存在的设备上的请求 . SerialPort启动的工作线程中的一个无法捕获的异常是一个常见的事故 . 听起来你的驱动程序确实错了,它会在MJ_CLOSE驱动程序请求上生成错误返回代码 . 对于一个驱动程序来说,这是一个合乎逻辑的事情,在所有设备不再存在之后,但是从你的目的来看是无法解决的 . 你有一个手柄,你不能关闭它 . 这是一条没有划桨的小溪 .

    .NET的每个主要版本都有一个针对SerialPort类的小补丁,试图尽量减少痛苦 . 但微软可以做的数量有限,捕捉所有错误并假装它们没有发生,最终导致不再提供良好诊断的类,即使有一个好的驱动程序 .

    所以实用的方法是:

    • 始终使用Windows中的“安全删除硬盘”托盘图标

    • 使用最新版本的.NET

    • 与供应商联系并要求更新驱动程序
      供应糟糕司机的

    • 沟渠供应商

    • 告诉你的用户,因为这是你唯一可以做的事情USB设备,拔掉它不能解决任何问题

    • 使您可以在UI中轻松关闭端口

    • 将USB连接器粘到端口上,因此无法将其移除

    第5个子弹也是程序员遇到麻烦的原因 . 编写串口代码并不能诊断出您往往会责怪硬件的软件问题 . 您可以使用硬件做很少的事情但拔下电源插头 . 馊主意 . 现在你有两个问题 .

相关问题