【问题标题】:User friendly exception error delphi用户友好的异常错误delphi
【发布时间】:2014-10-06 07:29:13
【问题描述】:

我有这个方法,我执行一个 sql 语句并在 try except 语句中捕获一个错误

AdoQuery := TAdoQuery.Create(self);
AdoQuery.connection := AdoConnection;
AdoQuery.SQL.Add(sqlStr);

AdoQuery.Prepared := true;

try
   begin
      AdoQuery.ExecSql;
      AdoQuery.Active := false;
   end;
except on e:eAdoError do
   ShowMessage('Error while creating the table: ' + e.Message);
end;

我可以捕捉到这样的错误并将其显示给用户,但它向用户显示了一些无用的信息。我想只显示错误的%msg 部分,看看图片:

我坚持e.MEssage 只允许我得到%msg 部分,但它给了我一个随机用户几乎无法理解的整个事情。在这种情况下我如何只获得有用的信息

表 reftabtest.rPCE 已经存在

谢谢。

【问题讨论】:

  • 查看Pos和Copy等基本字符串操作...
  • 你有 Pos()Copy() 函数来操作字符串。
  • @LURD 这不是硬编码吗?我怎么能确定总是有 %msg ?
  • 好吧,如果 %msg 不存在,则显示整个消息。

标签: delphi error-handling message


【解决方案1】:

你可以使用TADOConnection对象的Errors属性,你想要的是Error对象的Description成员。

在你的情况下:

function ParseOBDCError(ErrorDescription : String) : String;

var
  Ps : Integer;
  Pattern : String;

begin
 Pattern := '%msg:';
 Ps := Pos(Pattern, ErrorDescription);
 if Ps > 0 then
  begin
   Result := Copy(ErrorDescription, Ps+Length(Pattern)+1);
   // if you want, you can clean out other parts like < and >
   Result := StringReplace(Result, '<', , '', [rfReplaceAll]); 
   Result := StringReplace(Result, '>', , '', [rfReplaceAll]); 
   Result := Trim(Result);
  end
 else
  Result := ErrorDescription;
end;

...
 AdoQuery := TAdoQuery.Create(self);
 AdoQuery.connection := AdoConnection;
 AdoQuery.SQL.Add(sqlStr);
 AdoQuery.Prepared := true;

 try
  AdoQuery.ExecSql;
  AdoQuery.Active := false;
 except on e : Exception do
   begin
    if AdoConnection.Errors.Count > 0 then
     ShowMessageFmt('Error while creating the table: %s', 
                    [ParseOBDCError(AdoConnection.Errors[0].Description)])
    else
     ShowMessageFmt('something went wrong here: %s', [e.Message]);
   end;
 end;

【讨论】:

  • 这看起来很有希望。但是我的 try except 语句有问题。我做错了吗?除了 AdoQuery.Active 上的中断之外,它看起来不会去
  • 它不会像这样闯入代码,但显示的消息是 delphi 调试器,而不是我的除消息 grrr It's delphi 2006 btw
  • e.Message 说数组和字符串不兼容。当我只尝试第一个语句时,它显示与我的问题相同的错误,而不仅仅是 %msg 部分。现在它也显示了这两个奇怪的声明。我从调试器中禁用了通知异常,但它仍然显示消息而不破坏代码,然后它显示来自 except 语句的消息。这怎么可能
  • 对于 e.Message,它不适用于 ShowMEssageFmt。将 e.Message 放入 ShowMEssage 是可行的。但仍然显示两种说法。看起来调试器不想让我处理错误或 idk。并且仍然显示整个错误不仅是我感兴趣的部分:(
  • 是的,所以它不是调试器,而是我的代码。但是现在 .Description 显示了像 Delphi 那样的整个错误描述,我怎样才能得到 %mdg 部分?我真的必须使用 Pos 和复制吗?
【解决方案2】:

您的ShowMessage() 代码未显示该消息对话框。

首先,图标是错误的 - 那不是 ShowMessage 图标。
其次,您在邮件中添加的文本 ('Error while creating the table: ') 丢失了。

这意味着您的异常吞咽器没有捕获异常,因为它不属于 EADOError 类。所以发生的事情是应用程序的默认异常处理程序正在显示异常。


在我解释如何解决它之前,我需要指出您的异常吞咽器是错误的(您的异常吞咽器不应该被错误地命名为异常处理程序)。

因为你正在接受异常:如果另一个方法调用你的方法,它会错误地认为你的方法成功了,并且可能会做一些它不应该做的事情。你永远不应该编写假设没有重要的调用堆栈导致你的方法的代码。

吞咽向用户显示消息并没有帮助,因为它隐藏了程序其余部分的错误。尤其是因为,如您所见:在一个地方已经有代码告诉用户错误对程序的其余部分隐藏。 (你的问题是你想要一个更友好的信息。)


修复它:

首先找出实际的异常类是什么,这样你就能够捕捉到正确的错误。

现在你有很多选择,但最简单的如下:

  • 首先记录异常,最好使用调用堆栈。您不希望陷入用户收到友好消息但您作为开发人员在需要进行调试时丢失关键信息的情况。
  • 要获取调用堆栈,您可以考虑使用 Mad except、Exceptional Magic、JCLDebug 等第三方工具。
  • 现在向用户显示消息。
  • 最后拨打Abort。这会引发EAbort 异常,按照惯例,它是“静默异常”。它告诉程序的其余部分存在错误(因此假设一切正常,它不会做任何事情)。但按照惯例,任何进一步的异常处理程序都应该向用户显示另一条消息。这包括您问题中的默认处理程序对话框。
  • 如果默认处理程序不正确显示EAbort 消息,那么它应该被修复。

【讨论】:

  • 事实上我有一个退出而不是中止但没有复制到我的问题中。我试过 abort 它也一样,所以我想没有太大的不同。异常类我 EOleException 但它说未声明的标识符 EOleException 如果我在我的 except 语句中的 e:EOleException 上写例外
  • Exit;Abort; 之间存在巨大的差异。第一个只退出当前例程,但调用者不知道你有错误,只是继续处理,好像没有错一样。第二个退出调用堆栈中的所有例程,直到找到处理程序。 (例如在您的问题中显示对话框的默认处理程序。)该默认处理程序可以正确吞下异常,因为来自入口点的所有内容(无论是按钮单击、菜单项还是其他操作)都因错误而被放弃。您现在可以安全地等待下一步操作了。
  • 至于 EOleException,它包含在 ComObj 单元中。您必须使用单位才能使用类型。
  • 好的,我现在看到了不同之处。以及 EOleExcpetion 如何帮助我获得正确的信息?它和我得到简单的异常语句完全一样
  • @user28470: 因为那是整个 ADO 错误。这就是为什么您需要使用我的代码提取定义部分的原因。错误描述中的 %msg 特定于您正在使用的 ODBC 提供程序...
猜你喜欢
  • 2012-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-13
  • 2011-08-23
  • 1970-01-01
相关资源
最近更新 更多