在 Windows 中未调用 ExceptProc

ExceptProc not being called in Windows

提问人:Chris J 提问时间:10/23/2008 最后编辑:Jim McKeethChris J 更新时间:10/23/2008 访问量:820

问:

我目前正在尝试创建内置于我的 Windows 服务中的异常处理程序,该处理程序在未经处理的异常时将消息发送到另一个程序。我已经构建了该方法并使通信正常工作,但似乎每次我的程序抛出错误时,(我在代码中有一个提升调用来强制它。谁能解释我做错了什么?

用于解释的简化代码:

procedure unhandled();
  begin
    raise Exception.Create('Unhandled');
  end;

procedure ExceptionHandler(ExceptObject: TObject; ExceptAddr: Pointer);
  begin
    WriteLn('Display: ' + Exception(ExceptObject).Message);
    //send Message Here
  end;

我调用此代码来运行它:

WriteLn('Starting');    

ExceptProc := @ExceptionHandler;    

unhandled();

我希望输出是:

起始
显示:未处理

但它所做的只是显示:

开始

然后,Windows 会在大约 5 秒后返回命令提示符。

为什么没有正确调用处理程序?

P.S. 我一直在控制台应用程序中运行这些测试进行测试。

编辑:

以下是一些更多信息:

显然,当您分配了 ExceptProc 时,您的程序不应抛出正常的运行时 217 错误。我猜这就是 Windows 正在捕获的内容,但是从我所看到的,我的程序抛出了运行时错误,而且我也无法让 ErrorProc 捕获它。

德尔菲 异常

评论


答:

0赞 gabr 10/23/2008 #1

有趣。

如果在 Delphi IDE 中运行应用程序(尝试使用 2007),则会调用自定义异常处理程序,但如果从命令提示符运行它,则不会调用。

另一件有趣的事情 - 我将主程序代码更改为

begin
  WriteLn('Starting');
  try
    ExceptProc := @ExceptionHandler;
    Unhandled;
  finally Readln; end;
end.

并注意到只有在我按 Enter 键(以获取对 Readln 的一些输入)后才会显示异常消息。因此,处理程序不会在发生异常时调用,而是在处理异常时调用(在隐式 try..除了包装你所有的代码)。有意义。

一定是这种隐含的尝试..除了那时,但我在这台机器上缺少非 Delphi 调试器,无法进一步挖掘。也许其他人知道答案......

9赞 Barry Kelly 10/23/2008 #2

您缺少对 SetErrorMode() 的调用:

SetErrorMode(SEM_NOGPFAULTERRORBOX);

这是防止 OS 未经处理的异常筛选器显示对话框/显示调试器附加对话框所必需的。下面是一个完整的示例,在我的机器上按预期运行:

{$apptype console}

uses Windows, SysUtils;

procedure unhandled();
begin
  raise Exception.Create('Unhandled');
end;

procedure ExceptionHandler(ExceptObject: TObject; ExceptAddr: Pointer);
begin
  Writeln('here');
  WriteLn('Display: ' + Exception(ExceptObject).Message);
  Flush(Output);
  Halt(1);
end;

procedure Go;
begin
  unhandled;
end;

begin
  ExceptProc := @ExceptionHandler;
  SetErrorMode(SEM_NOGPFAULTERRORBOX);
  Go;
end.

请注意,SetErrorMode() 的效果在正在运行的进程中的所有线程中都是全局的。