2013-03-13 13 views
5

Moja aplikacja Delphi (przy użyciu XE3) musi obsługiwać wyjątek EInOutError występujący po usunięciu portu szeregowego USB. Aplikacja jest używana w środowisku testowym, więc nie może polegać na tym, że operator kliknie przycisk OK, aby zamknąć okno dialogowe Błąd aplikacji.Jak obsługiwać wyjątek, gdy port szeregowy USB zostanie nieoczekiwanie usunięty?

Próbowałem następujące:

  • „Wypróbuj .. z wyjątkiem” metody - to nie złapać tych wyjątków. Myślę, że to nie działa, ponieważ wyjątek nie jest spowodowany przez kod w bloku "try". Wygląda na wyjątek niższego poziomu na poziomie systemu.

  • Próbowałem dodać do formularza formularz "ApplicationEvents". Metoda OnException przechwytuje wyjątek "niestandardowy" wygenerowany przez moją aplikację, ale nie wyjątek na poziomie systemu.

  • Próbowałem również dodać globalny hak wyjątku (jak opisano w Is it possible to have a global exception hook?). To działa częściowo - pozwala mi to na robienie pewnych rzeczy w oknie dialogowym Błąd aplikacji, ale nie zatrzymuje okna błędu.

Byłbym wdzięczny za wszelkie pomysły!

+0

Jeśli blok try-except nie wychwytuje wyjątku, to albo wyjątek nie występuje tam, gdzie myślisz, że jest przechwytywany i obsługiwany przez inny kod wcześniej niż " próbuję to złapać, albo nie jest to wyjątek. Ponieważ nie możesz go złapać, skąd wiesz, że jest to wyjątek EInOutError? –

+0

Czy odbierasz wiadomość WM_DEVICECHANGE o typie DBT_DEVICEREMOVECOMPLETE i DBT_DEVTYP_PORT po odłączeniu portu USB? – MBo

+0

Witam Rob, pojawia się okno dialogowe zatytułowane "Błąd aplikacji", który pojawia się. Komunikat w oknie dialogowym to "Exception EInOutError in module Project1.exe at 001C7052." To uruchamia aplikację poza IDE/debuggerem. – Nigel

Odpowiedz

3

Wyjątki wynikające z usunięcia USB-Com są bardzo denerwujące. Polecam więc wyeliminowanie większości z nich.

Musisz przetworzyć wiadomość Windows WM_DEVICECHANGE i wykryć usunięcie portu. Następnie ustaw specjalną flagę i nie wykonuj żadnej operacji z portem z tą flagą! Jeśli USB-Com jest ponownie podłączony, podłącz ponownie port szeregowy. Niektóre kod, aby pomóc:

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

Dzięki za przykładowy kod! Poprawnie wykrywa, że ​​port został włożony i usunięty, nawet jeśli nie "otworzyłem" portu. Jednak nadal otrzymuję błąd aplikacji zaraz po usunięciu portu (nawet jeśli nic nie piszę). – Nigel

+0

To dość dziwne. Używam http://sourceforge.net/projects/comport/ i nie widzę takich błędów po usunięciu portu. Być może Twoja biblioteka wykonuje ciągłą ankietę portową?Możesz sprawdzić za pomocą http://technet.microsoft.com/en-us/sysinternals/bb896644.aspx – MBo

Powiązane problemy