views:

313

answers:

3

Do you know a way to trap, log, and re-raise exception in Delphi code? A simple example:

procedure TForm3.Button1Click(Sender: TObject);
begin
  try
    raise Exception.Create('Bum');
  except
    on E: Exception do
    begin
      MyHandleException(E);
    end;
  end;
end;

procedure TForm3.MyHandleException(AException: Exception);
begin
  ShowMessage(AException.Message);
  LogThis(AException.Message);  
  // raise AException; - this will access violate
end;

So I need to re-raise it in the except block but I was wondering if there is a better way to write my own method to handle and (on specific conditions) to re-raise exceptions.

+1  A: 

You should be able to just use the Raise command by itself to re-raise the exception:

begin
  MyHandleException(E);
  Raise;
end;
Mark Wilkins
I think that's exactly what he's trying not to do: have to put a **raise** after MyHandleException every time he calls it by putting the **raise** inside MyHandleException itself.
Mason Wheeler
@Mason: You may well be correct. I was probably reading it incorrectly. I'll delete my answer ... after a bit so you have a chance to see this comment :)
Mark Wilkins
I think it is right. He put the `raise` in a procedure called within the `except` block, which does not work. The `raise` needs to be precisely in the `except` block. If you write `raise AException` in the external procedure, you do get an access violation.
Andreas Rejbrand
Don't delete your answer. Your code snippet might be useful to others wondering how to re-`raise` an exception from within the `except` block. And learning that it is not possible to do it anywhere else.
PA
That makes sense - I'll leave it in place since I don't think the information is inherently wrong.
Mark Wilkins
Yep I'm trying to avoid raise on all try except blocks. But it seems unavoidable at this point :)Thanks guys!
Nik
+9  A: 

If you want to re-raise the exception only under certain conditions, write

procedure TForm3.Button1Click(Sender: TObject);
begin
  try
    raise Exception.Create('Bum');
  except
    on E: Exception do
    begin
      if MyHandleException(E) then
        raise;
    end;
  end;
end;

function TForm3.MyHandleException(AException: Exception): boolean;
begin
  ShowMessage(AException.Message);
  result := true/false;
end;
Andreas Rejbrand
this is good idea and I had it in mind but still I waned to know is there other code-less way to do it in a separate function.Thanks.
Nik
+1  A: 

You could try to use (system.pas):

function AcquireExceptionObject: Pointer;

AcquireExceptionObject returns a pointer to the current exception object and prevents the exception object from being deallocated when the current exception handler exits.

Note: AcquireExceptionObject increments the exception object's reference count. Make sure that the reference count is decremented when the exception object is no longer needed. This happens automatically if you use the exception object to re-raise the exception. In all other cases, every call to AcquireExceptionObject must have a matching call to ReleaseExceptionObject. AcquireExceptionObject/ReleaseExceptionObject sequences can be nested.

André
Interesting I will give a try to this. Thanks for the details.
Nik