我有一个用Delphi 2007编写的服务,我正在尝试捕获任何未知的异常。为on异常分配方法似乎不起作用('Forms.Application.OnException:= UnknownApplicationException')。 “UnknownApplicationException”似乎没有被调用 - 我将此归因于应用程序中没有表单的事实,因此该方法实际上从未被分配。除此之外,我还尝试在计时器上创建一个异常(在注释掉'Forms.Application.OnException:= UnknownApplicationException'后,它不会干扰)。定时器在服务启动后60秒触发:
procedure TProcessScheduler.Timer1Timer(Sender: TObject);
begin
try
Raise Exception.Create('THIS GIG SUCKS');
except
LogEvent(Name,rsUNKNOWN_EXCEPTION,EVENTLOG_AUDIT_FAILURE,0);
ExitCode:=-1;
Halt;
end;
end;
异常似乎永远不会被捕获 - 服务启动并且在此定时器触发后60秒后,我听到Windows错误声音但没有看到任何错误对话框 - 也许这可能是由于应用程序的事实是一项服务?永远不会调用'Halt'并且应用程序继续运行(我假设它等待某人在它创建的不可见错误对话框上单击ok)。有什么想法为什么“除外”下的代码没有被调用?提前致谢! KP
答案 0 :(得分:6)
重新分配Forms.Application.OnException
是一个坏主意,因为TServiceApplication.Run()
本身就是这样做的。你要么之前做过,那么你的任务就没有效果,或者你之后做了,在这种情况下你删除了已经实施的异常处理机制。
如果您将处理保留在原地,那么所有异常都将记录到Windows事件记录器中,这似乎是一项合理的服务。
答案 1 :(得分:2)
几点说明:
当您在try-except块中引发异常时,它不应该触发任何Application.OnException处理程序,只是因为未处理异常。
你是如何确定停止不被调用的?是否通过LogEvent记录异常?
在服务应用程序中,ExitCode和Halt的运行方式与普通Windows应用程序中的预期方式不同。呼叫暂停不会停止服务,应通过Windows服务控制管理器停止服务。
如果确实没有到达try-except块的除外部分,则意味着Windows已经插入,因为发生了一些不满意的事情。这可能是您正在调用的LogEvent方法中的内容。如果显示对话框或者也引发了异常,则不会到达ExitCode和Halt。
服务通常没有与之关联的桌面,因此显示对话框无效。
如果您需要服务来显示对话框(顺便说一下,服务是打算在没有用户交互的情况下运行),您需要使其具有交互性并使其在另一个用户帐户下运行而不是正常的“系统” “服务运行的帐户。您可以通过服务经理执行此操作。
答案 2 :(得分:1)
为什么要设置 Forms.Application ? AFAIK服务使用在SvcMgr中声明的Application变量,该变量声明为:
var
Application: TServiceApplication = nil;
此外,服务不应显示任何对话框,它可能无法访问用户桌面,您的对话框将挂起该服务。有很多方法可以显示对话框,但是当没有人类用户正在观看屏幕时,服务也可以运行。 将事件记录到事件日志中(或者如果您不喜欢它到文件,但事件日志有几个有用的功能,包括远程访问)。
答案 3 :(得分:0)
我创建自己的SvcMgr.pas文件版本以消除Application全局异常处理程序的就地挂钩,以便我可以实例化我自己的。我这样做是因为1)我找不到其他简单的方法,2)因为这个单元是一个独立的单元,只包含在Windows服务中,所以对其他单元的影响很小。您可以从我的网站下载代码,看看它是如何工作的。