Menu

#6 improved error handling

open
nobody
None
5
2014-08-15
2011-08-17
No

The current error handling will fail if a different API function was called since the error occurred since it relies on LastError being set correctly.
This change will solve this issue:

//Handle Exceptions
procedure TCustomComPort.CallException(AnException:Word; const WinError:Int64 =0);
var winmessage:string;
begin
if Assigned(FOnException) then
begin
/// ***** changed by twm 2010-08-12 --- start
if WinError > 0 then begin //get windows error string
winmessage := Format(SOSError, [WinError, SysErrorMessage(WinError)]);
// try Win32Check(winerror = 0); except on E:Exception do WinMessage:=e.message; end;
end;
/// ***** changed by twm 2010-08-12 --- end
FOnException(self,TComExceptions(AnException),ComErrorMessages[AnException],WinError, WinMessage);
end
else
if WinError > 0 then raise EComPort.Create(AnException, WinError)
else raise EComPort.CreateNoWinCode(AnException);
end;

The same code could go into EComport.Create:

// create exception with windows error code
constructor EComPort.Create(ACode: Integer; AWinCode: Integer);
var
winmessage: string;
begin
FWinCode := AWinCode;
FCode := ACode;
// ***** changed by twm --- start
// inherited CreateFmt(ComErrorMessages[ACode] + ' (Error: %d)', [AWinCode]);
if AWinCode then
winmessage := Format(SOSError, [WinError, SysErrorMessage(WinError)])
else
winmessage := SUnkOSError;
inherited Create(_('COM Port Error:') + ' '+ComErrorMessages[ACode]+' (Error: ' + winmessage + ')');
// ***** changed by twm --- end
end;

(If you give me write permissions to the svn repository I will commit these changes myself.
There is some more regarding error handling withing the event thread.)

Discussion

  • Brian Gochnauer

    Brian Gochnauer - 2011-08-17

    That does not compile; at least not under Delphi XE.
    SOSError is a number; Format function is expecting a "Format : string" as a first param

     
  • Brian Gochnauer

    Brian Gochnauer - 2011-08-17

    until you add SysConst.

     
  • Brian Gochnauer

    Brian Gochnauer - 2011-08-17

    Win32Check(winerror = 0);
    in the background Win32Check calls RaiseLastOSError(lasterror) making the call

    Error := EOSError.CreateResFmt(@SOSError, [LastError, SysErrorMessage(LastError)])

    which is essential the same call your making.
    I don't get why you think it relies on LastError?

     
  • Brian Gochnauer

    Brian Gochnauer - 2011-08-17

    I see it.

     
  • Thomas Mueller

    Thomas Mueller - 2011-08-18

    I should have tried to compile it fist :-(

    // create exception with windows error code
    constructor EComPort.Create(ACode: Integer; AWinCode: Integer);
    var
    winmessage: string;
    begin
    FWinCode := AWinCode;
    FCode := ACode;
    // ***** changed by twm --- start
    // inherited CreateFmt(ComErrorMessages[ACode] + ' (Error: %d)', [AWinCode]);
    if AWinCode <> 0 then
    winmessage := Format(SOSError, [AWinCode, SysErrorMessage(AWinCode)])
    else
    winmessage := SUnkOSError;
    inherited Create(_('COM Port Error:') + ' '+ComErrorMessages[ACode]+' (Error: ' + winmessage + ')');
    // ***** changed by twm --- end
    end;

     
  • Thomas Mueller

    Thomas Mueller - 2011-08-18

    @griangochnauer:
    Win32Check uses GetLastError to get the last error code which might have changed in between the failed api function and this call.

    SOSError is a resource string under Delphi 2007 and Delphi XE.