Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

CPort Lib exception handling

Status
Not open for further replies.

sggaunt

Programmer
Jul 4, 2001
8,620
GB
I use Cportlib to do several comms applications, but recently we have been developing USB comms equipment that generates virtual comm ports, that can be seen by components like CPort.

I have a problem in that if someone pulls out the usb connection this will raise an error in Cport thus
Code:
// perform asynchronous write operation
function TCustomComPort.WriteAsync(const Buffer; Count: Integer; var AsyncPtr: PAsync): Integer;
var
  Success: Boolean;
  BytesTrans: DWORD;
begin
  AsyncPtr^.Kind := okWrite;

  Success := WriteFile(FHandle, Buffer, Count, BytesTrans, @AsyncPtr^.Overlapped)
    or (GetLastError = ERROR_IO_PENDING);

  if not Success then
    raise EComPort.Create(CError_WriteFailed, GetLastError);

  SendSignals(lsTx, True);
  Result := BytesTrans;
end;

or at shut down when dissconecting the port
Code:
// abort all asynchronous operations
procedure TCustomComPort.AbortAllAsync;
begin
  if not PurgeComm(FHandle, PURGE_TXABORT or PURGE_RXABORT) then
    raise EComPort.Create(CError_PurgeFailed, GetLastError);
end;


if I attempt to handle this error thus
Code:
try
  Commportdriver.Write(Txbuff, preamble.value + 3);
except
  result := false;
end;

where that code was called ...
Code:
if not TxMessage(Acktoken) then
begin
  AbortComms := True;
  showmessage('A Comm port error has occurred: PClink is  unable to'+chr(13)+ .. etc
end;


The problem then propagates out to shutdown

Code:
 procedure TEmergiForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if commportdriver.Connected then
     try
        commportdriver.Close;
     except
        showmessage('Error Closing Comm port')
     end;

this doesnt handle the error correctly as windows will then display an application exception message.

I cant think of a way to handle the error so that the Cport can recover or at least exit gracefully.

Someone has suggested using the APRO comms library, but I don't know if this will solve the problem, and it will involve reworking the code?



Steve: Delphi a feersum engin indeed.
 
APRO has its own issues, I "patched" myself most of it's code to work like it should, but it is still not 100% stable (more like 99.95%).

down to your problem:

when closing the comport, the comport driver must close it's handle (like CloseHandle(CidEx) in APRO).

I suspect when pulling the usb adapter, the handle is no longer valid, thus resulting in an AV or something like that.

One question though: do you have to handle this kind of exception? Normally if the user tries to stop the USB device like he should, windows should reply the user that the device can't be stopped right now because it's in use.

What I mean is that pulling a USB device that's in use (like an USB key) is never a good idea, so this is the responsability of the user, not the software that uses it.

Cheers,
Daddy


-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Thanks for that Daddy

Cport Lib has this function which protected and is called on failed create or failed close, but not on any sort of Comms error. So I would have to change the CPort code to get at it, and it might not solve the problem.

Code:
// destroy serial port handle
procedure TCustomComPort.DestroyHandle;
begin
  if FHandle <> INVALID_HANDLE_VALUE then
    CloseHandle(FHandle);
end;

Basically implemented like this. But this also needs to be able to differentiate between errors as it is if a real comms error occurs the port handle is destroyed unnessecarily.

Code:
  try
       if TxAsync.Checked then
          begin
            InitAsync(P);
            CommPortDriver.WriteAsync(TxBuff, preamble.value + 3, P);
            Commportdriver.WaitForAsync(P);
            DoneAsync(P);
          end
       else
          Commportdriver.Write(Txbuff, preamble.value + 3);
    except
       CommPortDriver.DestroyHandle;
       result := false;
    end;

However I will put your (users responsibility not to yank the wire out) point to our customer, In all other respects the application is fine so he may go along with it as is!!


Steve: Delphi a feersum engin indeed.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top