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.)
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
until you add SysConst.
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?
I see it.
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;
@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.