禁用异常处理并让Windows捕获它?

6
我希望禁用Delphi的异常捕获功能,让Windows接管它,使其产生一个窗口,例如“AppName崩溃。调试、发送”,将其添加到应用程序事件中,创建内存转储等。默认情况下,Delphi在TApplication.Run过程中捕获所有异常...我如何避免修改Forms.pas的情况下实现这一点?

6
我强烈建议不要这样做,并强烈推荐使用像MadExcept这样的工具,或者甚至是JEDI项目中的异常处理程序。 - Nick Hodges
这是为了调试目的。通过这样做,我想捕获项目中使用的外部DLL中的错误,这就是为什么我希望Windows处理事情。我在生产中使用madExcept。 - djsoft
4个回答

8
你可以添加一个 OnException 处理程序来重新引发异常:
class procedure TMainForm.OnException(Sender: TObject; E: Exception);
begin
  raise Exception(AcquireExceptionObject);
end;

initialization
  Application.OnException := TMainForm.OnException;

我不确定你为什么想这样做。更正常的做法是使用像 madExcept 或 EurekaLog 这样的工具来显示一个错误对话框,其中包含比系统对话框更有用的信息。


这个有效 :) 谢谢!像madExcept这样的工具在调试自己的代码时提供了有用的信息,但当问题出现在第三方DLL中时,它并没有那么有帮助。 - djsoft

4
您可以将 JITEnable 设置为 '1' 或更高(默认为 '0')。使用 '1',非本机异常会被处理;使用更高的值,所有异常都将由JIT或WER(取决于系统)处理。
虽然这可能不是您想要的解决方案。使用此解决方案,任何符合条件的异常都将传递给操作系统,无论它们是否在代码中得到处理。澄清(在调试器外运行):
procedure TForm1.Button1Click(Sender: TObject);
begin
  raise EAccessViolation.Create('access denied');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  try
    PInteger(0)^ := 0;
  except
  end;
end;

initialization
  JITEnable := 1;

第一个例子是本地异常,当 JITEnable 为1时,它将由应用程序异常处理机制处理。但第二个例子会触发JIT/WER。

3
谢谢! JITEnable := 2 看起来就是我在寻找的东西。 - djsoft

3

添加自己的处理程序。 Application.OnException 可能是您想要的。这比让 Windows 自己处理更好,因为在不同的环境下会得到不同的行为。例如,如果打开了 Windows 错误报告,则会询问用户是否要将错误报告发送给 MS。

像 Heffernan 先生一样,我建议您查看类似 EurekaLog 的东西。


1

AS. 我同意上面的声音,这个愿望相当奇怪。 我也同意实际上挂钩 TApplication.OnException 可能已经足够了(“如果看起来像鸭子…”)

但是如果你真的想让 RTL 对异常毫不在意,也有办法。

异常处理程序是低级 RTL 的插件,就像堆管理等一样。

您可以查看 KOL(关键对象库)。 在 Delphi 5 时代,我成功制作了2KB大小的 DLL。

那需要放弃很多通常被认为是理所当然的功能。其中包括异常。

要在KOL的系统RTL替换中启用异常,您必须进行一些 $DEFINE 操作,然后解锁将异常支持添加到 IDE 的代码。

我相信您仍然可以获得那个模块化的RTL版本,并搜索该 $IfDef,看看哪些代码被替换为哪些代码。 我相信您有很大的机会撤消它,使 Windows 避免调用 Delphi RTL 超出异常范围。 我记不清细节了,但我相信 Delphi RTL 异常处理程序只是在 Windows 核心中注册为回调。您可能可以注销它(注册 nil 回调)。 我相信您可以在股票 RTL 中找到它,但是 KOL 的模块化 RTL 会使搜索变得更加容易。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接