0
votes

I'm having this funny issue with Delphi XE where I create a try/except/finally statement and when the application generate an exception the except block is never called it jump straight to the finally block, I tried few things like invert the try/except/finally to try/finally/except, try to change the try blocks to different places, clean the code and recompile in case was a Delphi issue but noting seems to work.

What I'm trying to accomplish here is to show a dialog message to the user and after clean up the code in case of a crash.

procedure CallbackExport(Sender: TObject);
var
  SaveDlg: TSaveDialog;
  FileName: string;
begin
  SaveDlg := TSaveDialog.Create (nil);
  try
    try
      SaveDlg.Title := 'Export';
      SaveDlg.InitialDir := GetSystemPath(CSIDL_DESKTOP);
      SaveDlg.Options := [ofOverwritePrompt, ofEnableSizing];

      case (Sender as TMenuItem).Tag of
        cnExcel: begin
          SaveDlg.Filter := 'Excel File (*.xls)|*.xls';
        end;
        cnHtml: begin
          SaveDlg.Filter := 'HTML File (*.html)|*.html';
        end;
        cnTxt: begin
          SaveDlg.Filter := 'Text File (*.txt)|*.txt';
        end;
        cnCsv: begin
          SaveDlg.Filter := 'Comma Seperated File (*.csv)';
        end;
        cnXml: begin
          SaveDlg.Filter := 'XML file (*.xml)|*.xml';
        end;
      end;
      if not SaveDlg.Execute(self.Handle) then
        Exit;
      FileName := SaveDlg.FileName;

      case (Sender as TMenuItem).Tag of
        cnExcel: begin
          ExportGridToExcel(FileName, tvdGrid);
        end;
        cnHtml: begin
          ExportGridToHTML(FileName, tvdGrid);
        end;
        cnTxt: begin
          ExportGridToText(FileName, tvdGrid);
        end;
        cnCsv: begin
          ExportGridToText(FileName, tvdGrid, true, true, ',', '', '', 'CSV');
        end;
        cnXml: begin
          ExportGridToXML(FileName, tvdGrid);
        end;
      end;
    except
      on e: exception do
      begin
        ShowMessage('An error occurred while saving the file ' + FileName + #13#10 + 'With a message: ' + E.Message);
        StvdAudit.tvdAudit('Error saving file, reason: ' + E.Message);
      end;
    end;
  finally
    SaveDlg.Free;
  end;
end
3
This code looks like it should work. Can you provide a reproducible example that we can actually compile and test?Mason Wheeler
How do you know an exception is being generated? Try to explicitly raise an exception and see what happens. Put "raise exception . create ( 'Here is an exception' );" after the second TRY.David Dubois
I agree. There is very little in this code, as it is shown, that would raise an exception to begin with.Remy Lebeau
My guess is that maybe the ExportGrid functions are eating/handling the exceptions (try..except inside them). Since the call to these functions are the last executable line in the try..finally block, it would appear as it's jumping to the finally statement. To confirm that, you could just add a ShowMessage right before your except clause and see if you get that message after the IDE shows you the exception. If that's the case, you'll have to not handle the exception inside that functions or re-raise it on the except block (just raise;). I don't know if I made myself clear...GabrielF
I never worked with DevExpress, so I can't really assert anything, but I'm still guessing the ExportGrid functions are handling the exception. I suggest you set a break point and go all the way inside the DevExpress source code ([F7] on the function) to track down where the exception is happening and where it's being handled. You should have the source code, but maybe not in the Library Path (that avoids recompiling, which saves time). But when the debugger asks for the .pas file, locate it and select on the debugger (usually components come with a source dir inside it's tree).GabrielF

3 Answers

7
votes

If an exception is raised inside the try/except, and not handled by code further down the call stack, it will be caught by your exception handler.

You are claiming the ExportGridToXXX is raising an exception that is not caught by the exception handler in your code. But that claim cannot be true. Either no exception is raised, or ExportGridToXXX already handles the exception.

On the more general subject of exception handling, the general policy should be not to handle them if at all possible. You should only handle them in case you need to stop the exception propagating, and need to deal with the exception at this point in the code. Normally, particularly in a UI program, you would simply let the exception be handled by the top-level exception handler.

As well as that point, you code swallows all exceptions, irrespective of their type. That's bad practice. Supposing that you do want to handle exceptions raised by ExportGridToXXX, you should only handle the exception classes that are expected. For instance, you might encounter EAccessViolation for which your app's policy is to terminate. But since you swallowed it, treating it in the same handler used to trap sharing violations, you cannot apply that policy. Always be discerning in your handling of exceptions.

0
votes

Do the Export(smth) functions reside in a separate DLL? Then your application's Exception class is not the same as external DLL's Exception class.

0
votes

Your exception handler is swallowing the exception, try re-raising instead:

on e: exception do 
begin
  StvdAudit.tvdAudit('Error saving file, reason: ' + E.Message);
  raise exception.create('An error occurred while saving the file ' + FileName + #13#10 +       'With a message: ' + E.Message);
end;