如果未使用 CloseHandle 正确关闭,则重新打开串行端口失败

Posted

技术标签:

【中文标题】如果未使用 CloseHandle 正确关闭,则重新打开串行端口失败【英文标题】:Reopening serial port fails if not closed properly with CloseHandle 【发布时间】:2010-06-01 09:03:28 【问题描述】:

我在 Windows 上使用被视为虚拟串行端口的 USB 设备。我可以使用 CreateFile 和 ReadFile 函数与设备通信,但在某些情况下,我的应用程序不会调用 CloseHandle(当我的开发应用程序崩溃时)。之后,对 CreateFile 的所有调用都失败(ERROR_ACCESS_DENIED),唯一的解决方案是再次登录我的计算机。有没有办法以编程方式强制关闭打开的句柄(或重新打开)?

【问题讨论】:

这有什么变化吗? Win7 + .NET 4.5 也有同样的问题,只有 USB 重新插入有帮助 =( 【参考方案1】:

这当然不正常。在进程终止后,Windows 会自动关闭所有打开的句柄。这一定是您的 USB 设备驱动程序中的一个缺陷,尽管很难看出它是如何搞砸的。然而,模拟串行端口的那些是出了名的糟糕。好吧,除了希望制造商更新驱动程序之外,您无能为力。或者其他制造商的设备。

【讨论】:

感谢您的所有回答。看起来我不是唯一一个遇到 USB 转串口问题的人。我目前的解决方法是尝试在循环中调用 CreateFile,直到它成功。现在似乎可以工作,可能它不会在任何其他计算机上工作。 我注意到有时我必须在 windows 和/或设备驱动程序意识到设备不再使用之前关闭我正在调试的 IDE。看起来不应该是这样,但确实如此。【参考方案2】:

我同意之前的两个帖子。

    这不是正常情况。 拔出 USB 设备通常会有所帮助。

此问题与负责实现虚拟 COM 端口的 FTDI 驱动程序中的故障有关。 另一方面,这些“故障”与 USB 设备的各种故障有关。 (当然,这并不能证明 FTDI 驱动程序是合理的)。

顺便说一句,一些 FTDI 驱动程序还有其他几个已知问题:

有时调用CloseHandle 只是挂起调用线程。 有时应用程序在任务管理器中仍然“可见”,即使在它关闭后也是如此。任务管理器不能终止应用程序,调试器也不能附加到它上面。它的 EXE 文件被锁定(无法删除)。

在这些情况下,通常立即拔出 USB 设备会有所帮助。 FTDI 驱动程序,似乎正在“等待某事”醒来。

【讨论】:

经过进一步测试后,我注意到即使关闭与 CloseHandle 的连接,CreateFile 也会失败。幸运的是,在延迟的循环中调用 CreateFile 似乎可以解决问题。通常需要不到 10 次尝试重新打开设备。【参考方案3】:

是否有可能您的崩溃程序的某些线程或子进程仍在运行并持有文件句柄的副本?也许调试器进程仍然打开?如果是这样,那些可能会使设备保持打开状态。为了确定,我会检查任务管理器;如果是这样,强制终止剩余进程可能会解决问题。

【讨论】:

任务管理器显示我的应用程序进程正常退出。看起来这是一个设备驱动程序错误。【参考方案4】:

您不希望发生的另一件事是打开 USB 串行端口并且用户将 USB 拉到串行适配器。该错误已经(是?)存在了很长时间。这是一个错误的答案

“Microsoft 于 2009 年 3 月 27 日下午 4:03 发布 你好, 感谢您报告此问题。我们已意识到此问题并已修复 .NET 框架的下一个主要版本。

如果您有任何疑问,请重新激活此问题,我会尽快回复。 谢谢, 金汉密尔顿 基类库”

不知道问题是否相关。 Microsoft Connect 报告了多个 USB 串行错误。

【讨论】:

【参考方案5】:

也许您可以在主代码周围添加一个 Try catch close,并在 catch close 中调用 CloseHandle。那么即使程序crash,也会调用CloseHandle。

try

   HANDLE hPort = NULL;
   hPort = CreateFile(...);
   // You code...


catch (...)

   if (hPort != NULL)
       CloseHandle(hPort);

【讨论】:

【参考方案6】:

尝试拔下设备并重新插入。有时需要提醒 Windows 没有人再连接到该端口。

【讨论】:

这与Windows无关。正如 valdo 和 Hans 指出的那样,是设备驱动程序导致了问题。

以上是关于如果未使用 CloseHandle 正确关闭,则重新打开串行端口失败的主要内容,如果未能解决你的问题,请参考以下文章

如果应用程序未以编程方式安装 firebase 动态链接,则重定向到 iOS App Store

如果用户未登录 Laravel,则重定向到登录页面

如果域不正确则重定向

如果未登录,则重定向 html 页面

如果页面未被访问,则重定向到另一个页面 PHP

如果用户未登录 Laravel,则重定向到登录