How to handle an exception when the USB serial port is removed unexpectedly?

My Delphi application (using XE3) should handle the EInOutError exception that occurs when the USB-Serial port is removed. The application is used in a test environment, so it cannot rely on the operator to click the OK button to close the Application Error dialog box.

I tried the following:

  • The "try .. except" method - this does not eliminate these exceptions. I think this does not work because the exception is not caused by the code in the try block. This is similar to a “system level” exception of a lower level.

  • I tried adding the "ApplicationEvents" component to my form. The OnException method catches the "Custom" exception thrown by my application, but not the system level exception.

  • I also tried adding a global exception hook (as described in Is it possible to have a global exception cache? ). This partially works - it allows me to make messages until the Application Error dialog box, but it does not stop the error dialog.

I would be grateful for any ideas!

+5
source share
1 answer

Exceptions due to USB-Com removal are very annoying. Therefore, I would recommend eliminating most of the reasons for them.

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;
+3

All Articles