如何在意外删除USB串口时处理异常?

时间:2013-03-13 12:15:09

标签: delphi exception-handling

我的Delphi应用程序(使用XE3)需要处理移除USB串行端口时发生的EInOutError异常。应用程序在测试环境中使用,因此不能依赖操作员单击“确定”按钮来关闭“应用程序错误”对话框。

我尝试了以下内容:

  • “try .. except”方法 - 这不会捕获这些异常。我认为这不起作用,因为异常不是由“try”块中的代码引起的。它似乎是一个较低级别的“系统级”例外。

  • 我尝试在表单中添加“ApplicationEvents”组件。 OnException方法捕获由我的应用程序生成的“自定义”异常,但不捕获系统级异常。

  • 我还尝试添加全局异常挂钩(如Is it possible to have a global exception hook?中所述)。这部分有效 - 它允许我在“应用程序错误”对话框之前执行之前的操作,但不会停止错误对话框。

我很感激任何想法!

1 个答案:

答案 0 :(得分:3)

因USB-Com移除而引起的异常非常烦人。所以我建议消除它们的大部分原因。

您必须处理Windows消息WM_DEVICECHANGE并检测端口删除。然后设置特殊标志,不要对带有此标志的端口进行任何操作!如果再次插入USB-Com,则重新启动串口。一些代码可以提供帮助:

    const
      DBT_DEVICEARRIVAL = $8000;
      DBT_DEVICEREMOVECOMPLETE = $8004;
      DBT_DEVICEQUERYREMOVE = $8001;
      DBT_DEVTYP_PORT = 3;

    type
       PDevBroadcastHdr = ^TDevBroadcastHdr;
       TDevBroadcastHdr = packed record
        dbcd_size: DWORD;
        dbcd_devicetype: DWORD;
        dbcd_reserved: DWORD;
      end;

      PDEV_BROADCAST_PORT = ^TDEV_BROADCAST_PORT;
      TDEV_BROADCAST_PORT = packed record
        dbcp_size: DWord;
        dbcp_devicetype: DWord;
        dbcp_reserved: DWord;
        dbcp_name: array[0..MAX_PATH] of Char;
      end;

    ...
    procedure WMDEVICECHANGE(var Msg: TMessage); message WM_DEVICECHANGE;
    ...

procedure TForm1.WMDEVICECHANGE(var Msg: TMessage);
var
  prt: PDEV_BROADCAST_PORT;
  s: string;
begin

  if Msg.wparam =  DBT_DEVICEREMOVECOMPLETE then
    if PDevBroadcastHdr(Msg.lParam)^.dbcd_devicetype = DBT_DEVTYP_PORT then
      begin

        b_PortRemoved := True; //check this flag before each operation with port.


        prt := PDEV_BROADCAST_PORT(PDEV_BROADCAST_PORT(Msg.lParam));
        s := prt.dbcp_name;
        ShowMessage('ComPort ' + s + ' has been removed. What can I do?');
    end;

  if Msg.wparam =  DBT_DEVICEARRIVAL then
    if PDevBroadcastHdr(Msg.lParam)^.dbcd_devicetype = DBT_DEVTYP_PORT then begin
       // USB-COM plugged, you can find it and make some reinitialisation
    end;


end;