如何从包含 D2007 的异常块中使用 Halt(n) 返回错误代码?
更新:似乎是D2007特有的。它在 D2010 中的工作方式就像在旧版本中一样。
我想根据 Eception Handler 块中捕获的异常类型返回退出代码,例如:
program test;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
Exitcode: Integer;
begin
Writeln('Enter error code:');
Readln(Exitcode);
try
raise EExternal.Create('sdsdkfjh');
except
on E:EExternal do
begin
Writeln(E.Classname, ': ', E.Message);
Halt(Exitcode);
end;
end;
end.
不幸的是,在 D2007 中,从异常块调用 Halt(n) 总是返回退出代码 1,无论您将什么传递给 Halt()。
显然,因为从异常处理程序退出会调用 Finalize,它会清除挂起的(非中止)异常,调用 SysUtils.ExceptHandler:
procedure ExceptHandler(ExceptObject: TObject; ExceptAddr: Pointer); far;
begin
ShowException(ExceptObject, ExceptAddr);
Halt(1); // <= @#$##@#$!
end;
并且无论我想要什么退出代码,我都会得到 Halt(1)
!
所以问题是:
如何根据引发的异常简单地返回所需的退出代码?
Update: It seems to be specific to D2007. It works in D2010 like it worked in older version.
I would like to return an exit code depending on the type of Exception caught in the Eception Handler block like:
program test;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
Exitcode: Integer;
begin
Writeln('Enter error code:');
Readln(Exitcode);
try
raise EExternal.Create('sdsdkfjh');
except
on E:EExternal do
begin
Writeln(E.Classname, ': ', E.Message);
Halt(Exitcode);
end;
end;
end.
Unfortunately in D2007, calling Halt(n) from an Exception block always returns an Exit code 1, no matter what you pass to Halt().
Apparently because exiting from an Exception handler calls Finalize, which clears the pending (non Abort) Exceptions, calling SysUtils.ExceptHandler:
procedure ExceptHandler(ExceptObject: TObject; ExceptAddr: Pointer); far;
begin
ShowException(ExceptObject, ExceptAddr);
Halt(1); // <= @#$##@#$!
end;
And no matter what exit code I wanted I get that Halt(1)
!
So the question is:
How can I simply return the desired Exit code depending on which Exception was raised?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这行得通吗?
还是这个?
无论如何:这是 D2007 中的一个错误,已在 D2010 中修复。
Will this work?
Or this?
Anyway: it's a bug in D2007, which was fixed in D2010.
实际上...它似乎按预期工作....
我使用了你的代码...
在Delphi 5中编译,然后在XP下的DOS框中运行它...
请注意,DOS错误级别限制在以下范围内0 到 65535。回显 %errorlevel% 是查看错误级别的最快方法。
不要忘记读取错误级别会清除它。
Actually... it seems to work as intended....
I used your code...
Compiled in in Delphi 5, then ran it in a DOS box under XP...
Note that DOS Error Levels are restricted to the range of 0 to 65535. Echoing %errorlevel% is the quickest way to see the error level.
Don't forget that reading the errorlevel clears it.
如果您想立即中止程序而不进行任何清理,并返回退出代码,请尝试 退出进程。不过,请参阅该文章了解有关使用 ExitProcess 的一些注意事项。
If you want to immediately abort the program without any cleanup, and return an exit code, try ExitProcess. See the article for a few caveats on using ExitProcess, though.
使用halt(I) 会产生内存泄漏(您可以看到,如果使用ReportMemoryLeaksOnShutdown:=true 启用了FastMM MemoryLeaks;)
最好使用“干净”退出并在退出之前设置ExitCode。
例如,在控制台应用程序的主要部分中:
Using halt(I) generates memory leaks (you can see that if you enabled the FastMM MemoryLeaks with ReportMemoryLeaksOnShutdown:=true;)
It's much better to use a "Clean" Exit and set ExitCode prior to exiting.
In a main section of a console app for instance:
如果内置的异常处理函数不符合您的要求,请将其替换为您自己的:
将其分配给全局
System.ExceptProc
程序启动时的变量:我已实现它以使用全局
ExitCode
变量。如果它仍然是默认值 0,则该函数将恢复为以 1 退出的原始 Delphi 行为,但如果退出代码已被设置为其他值,则该函数将以该值停止。Halt
所做的第一件事是设置全局ExitCode
变量,因此您的代码不需要进一步更改(尽管我会为Exitcode< /代码> 变量)。您对
Halt
的调用将设置全局ExitCode
变量,然后继续关闭程序。异常处理程序将注意到ExitCode
已设置,并使用该值而不是 1 重新调用Halt
。If the built-in exception-handling function doesn't do what you like, then replace it with your own:
Assign that to the global
System.ExceptProc
variable when your program starts:I've implemented it to use the global
ExitCode
variable. If it's still at its default value of 0, then the function reverts to the original Delphi behavior of exiting with 1, but if the exit code has already been set to something else, then this will halt with that value instead. The first thingHalt
does is set the globalExitCode
variable, so your code should need no further changes (although I'd choose a different name for theExitcode
variable). Your call toHalt
will set the globalExitCode
variable and then proceed to shut down the program. The exception handler will notice thatExitCode
is already set and re-callHalt
with that value instead of 1.