如何在Delphi应用程序中调用APPCRASH事件?

5
你可能认为这是个愚蠢的问题,但我很好奇如何通过APPCRASH错误(也称为“不发送”错误)终止我的Delphi应用程序。
提前感谢。

@David:我只是想知道,像Photoshop等许多应用程序一样。 - Javid
2
这些应用程序并不是有意以那种方式终止的! - David Heffernan
2个回答

13

您可以通过在System中设置全局变量JITEnable来启用此功能。如果将其设置为1,则所有外部异常(如访问冲突,非法指令和任何非Delphi异常)都会触发所需的反应。如果将其设置为2,则任何异常都会触发该行为。无论哪种情况,这只会在您调试应用程序时发生。调试器总是会第一时间获取并通知您即将发生的问题。以下是一个简单的示例:

{$APPTYPE CONSOLE}
uses
  SysUtils;

begin
  try
    JITEnable := 2;
    raise Exception.Create('Error Message');
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

它能够运行,但只有一个问题。该应用程序会卡住,当我们想要关闭它时,我们无法关闭(除非使用任务管理器)。尽管答案看起来很标准,但我没有将其标记为已接受的答案。 - Javid
2
如果你只是想“快速终止”你的应用程序,你可以这样做:TerminateProcess(GetCurrentProcess, 1); 这将立即结束你的应用程序而不发出任何声音。当然,如果你的应用程序在那个点上正在执行重要任务,事情可能会非常快地变得不稳定。 - Allen Bauer
@Allen:非常感谢你,亲爱的Allen Bauer。你提出的建议很有用。我已将其标记为已接受的答案。让我解释一下我之前评论的确切意思。当我将JITEnable设置为2时,但是当我引发异常并要求Windows关闭我的应用程序时,它不会关闭,而会一直停留,直到我使用任务管理器终止该进程。 - Javid
@Javid,这很奇怪。我的示例是否也对您展现了相同的行为?如果您有一个更小的测试用例出现了这种情况,请将其输入到我们的缺陷跟踪系统http://qc.embarcadero.com中。我正在使用最新版本(Delphi XE后内部构建)。我怀疑可能还有其他原因导致您的应用程序挂起。您的线程是否在IO请求或某些操作系统同步对象上被阻塞? - Allen Bauer
@Allen:不,我没有。无论如何,我正在使用D2010,而我没有XE;我应该仍然向QC报告吗? - Javid

3

不要使用任何解决异常处理的替代路径,而是直接避免使用它们:

function Crash(Arg: Integer): Integer; stdcall;
begin
  Result := PInteger(nil)^;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  TID: Cardinal;
begin
  CloseHandle(CreateThread(nil, 0, @Crash, nil, 0, TID));
end;

Crash在新的线程中执行。这个线程没有任何异常处理程序。在这样的线程中出现的任何异常都会对应用程序造成致命影响。


1
-1 这并没有回答实际问题,即如何使用操作系统功能触发特定的异常处理方式。Allen的回答解决了这个问题;而你的回答展示了在线程和代码中处理异常的绝对错误方式。 - Ken White
1
我不是。问题是“如何触发应用程序崩溃?”,而你的答案是“在线程中引用空指针”。Delphi的默认异常处理程序将捕获大多数(但不是全部)异常并显示一个异常对话框;除了故意编写可怕的代码外,唯一的触发应用程序崩溃的方法就是Allen描述的方式。如果你不同意,很抱歉,但是从所获得的票数来看,Allen的答案更正确,而且我认为你的答案根本不正确。这就是SO的工作方式;今天不是你第一天来到这里,所以你现在应该知道。 - Ken White
2
@Ken White,你的说法完全错误。在做出这样的断言之前,请花些时间分析一下这段代码。裸线程没有任何异常处理程序,包括Delphi。不会有Delphi错误对话框弹出。不喜欢解引用?好吧,写上"raise Exception" - 这没关系。 - Alex

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