Как вернуть код ошибки с Halt (n) из блока исключений с D2007?
обновление: похоже, это специфично для D2007. Он работает в D2010, как и в более старой версии.
Я хотел бы вернуть код выхода в зависимости от типа исключения, пойманного в блоке обработчика Eception, например:
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 неважно, что вы проходите, чтобы остановить().
видимо, потому что выход из Обработчик исключений вызывает Finalize, который очищает ожидающие (не прерываемые) исключения, вызывая SysUtils.ExceptHandler:
procedure ExceptHandler(ExceptObject: TObject; ExceptAddr: Pointer); far;
begin
ShowException(ExceptObject, ExceptAddr);
Halt(1); // <= @#$##@#$!
end;
и независимо от того, какой код выхода я хотел, я получаю это Halt(1)
!
Итак, вопрос:
Как я могу просто вернуть желаемый код выхода в зависимости от того, какое исключение?
5 ответов
будет ли это работать?
NeedHalt := False;
try
raise EExternal.Create('sdsdkfjh');
except
on E:EExternal do
begin
Writeln(E.Classname, ': ', E.Message);
NeedHalt := True;
end;
end;
if NeedHalt then
Halt(Exitcode);
или это?
try
raise EExternal.Create('sdsdkfjh');
except
on E:EExternal do
begin
Writeln(E.Classname, ': ', E.Message);
AcquireExceptionObject;
Halt(Exitcode);
end;
end;
на самом деле... кажется, это работает по назначению....
я использовал ваш код...
program test1;
{$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.
скомпилирован в Delphi 5, затем запустил его в поле DOS под XP...
C:\>test1
Enter error code:
111
EExternal: sdsdkfjh
C:\>echo %errorlevel%
111
C:\>
обратите внимание, что уровни ошибок DOS ограничены диапазоном от 0 до 65535. Повторение %errorlevel% - самый быстрый способ увидеть уровень ошибки.
Не забывайте, что чтение errorlevel очищает его.
Если вы хотите немедленно прервать программу без очистки и вернуть код выхода, попробуйте ExitProcess. См. Статью для нескольких предостережений об использовании ExitProcess.
использование halt (I) создает утечки памяти (вы можете видеть, что если вы включили Fastmm MemoryLeaks с ReportMemoryLeaksOnShutdown:=true;)
гораздо лучше использовать "чистый" выход и установить ExitCode до выхода.
в главном разделе консольного приложения, например:
ExitCode:=I;
exit;
если встроенная функция обработки исключений не делает то, что вам нравится, замените ее своей собственной:
function ExitCodeExceptHandler(ExceptObject: TObject; ExceptAddr: Pointer);
begin
ShowException(ExceptObject, ExceptAddr);
if ExitCode = 0 then
ExitCode := 1;
Halt(ExitCode);
end;
назначьте это глобальному System.ExceptProc
переменная при запуске программы:
ExceptProc := @ExitCodeExceptHandler;
я реализовал его, чтобы использовать global ExitCode
переменной. Если он по-прежнему имеет значение по умолчанию 0, то функция возвращается к исходному поведению Delphi выхода с 1, но если код выхода уже установлен в что-то еще, тогда это остановится на этом значении. Первым делом Halt
does устанавливает глобальный ExitCode
переменная, поэтому ваш код не должен нуждаться в дальнейших изменениях (хотя я бы выбрал другое имя для Exitcode
переменной). Ваш звонок в Halt
задает глобальную ExitCode
переменная, а затем приступить к завершению работы программы. Обработчик исключений заметит, что ExitCode
уже установлен и повторный вызов Halt
С этим значением вместо 1.