Comment retourner un code d'erreur avec Halt (n) à partir d'un bloc d'exception avec D2007?
-
25-09-2019 - |
Question
Mise à jour : Il semble être spécifique à D2007. Il travaille dans D2010 comme il a travaillé dans l'ancienne version.
Je voudrais revenir un code de sortie en fonction du type d'exception pris dans le bloc gestionnaire ÉCEPTION comme:
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.
Malheureusement, dans D2007, appelant Halt (n) à partir d'un bloc d'exception renvoie toujours un code de sortie 1 , peu importe ce que vous passez à Halt ().
Il semble que la sortie d'un appel gestionnaire d'exception Finaliser, qui efface les en attente (non Abort) Exceptions, appelant SysUtils.ExceptHandler:
procedure ExceptHandler(ExceptObject: TObject; ExceptAddr: Pointer); far;
begin
ShowException(ExceptObject, ExceptAddr);
Halt(1); // <= @#$##@#$!
end;
Et peu importe ce que le code de sortie que je voulais que je reçois Halt(1)
!
La question est: Comment puis-je retourner simplement le code de sortie désiré en fonction de quelle exception a été soulevée?
La solution
Est-ce que ce travail?
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);
Ou cela?
try
raise EExternal.Create('sdsdkfjh');
except
on E:EExternal do
begin
Writeln(E.Classname, ': ', E.Message);
AcquireExceptionObject;
Halt(Exitcode);
end;
end;
Quoi qu'il en soit: c'est un bogue dans D2007, qui a été fixé dans D2010 .
Autres conseils
En fait ... il semble fonctionner comme prévu ....
je votre code ...
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.
Compilé dans Delphi 5, il a couru dans une boîte DOS sous XP ...
C:\>test1
Enter error code:
111
EExternal: sdsdkfjh
C:\>echo %errorlevel%
111
C:\>
Notez que les niveaux d'erreur DOS sont limités à la plage de 0 à 65535. Faisant écho% ERRORLEVEL% est le moyen le plus rapide pour voir le niveau d'erreur.
Ne pas oublier que la lecture du errorlevel efface.
Si vous voulez abandonner immédiatement le programme sans nettoyage, et retourner un code de sortie, essayez ExitProcess . Voir l'article pour quelques mises en garde sur l'utilisation ExitProcess, cependant.
Utilisation de l'arrêt (I) génère des fuites de mémoire (vous pouvez voir que si vous avez activé les MemoryLeaks FastMM avec ReportMemoryLeaksOnShutdown: = true;)
Il est préférable d'utiliser un « Clean » EXIT et ExitCode avant la sortie.
Dans une section principale d'une application de la console par exemple:
ExitCode:=I;
exit;
Si la fonction intégrée gestion des exceptions ne fait pas ce que vous voulez, puis le remplacer par votre propre:
function ExitCodeExceptHandler(ExceptObject: TObject; ExceptAddr: Pointer);
begin
ShowException(ExceptObject, ExceptAddr);
if ExitCode = 0 then
ExitCode := 1;
Halt(ExitCode);
end;
assignons à l'économie mondiale System.ExceptProc
variable lorsque le début du programme:
ExceptProc := @ExitCodeExceptHandler;
Je l'ai mis en œuvre pour utiliser la variable globale ExitCode
. Si elle est toujours à sa valeur par défaut de 0, la fonction revient au comportement Delphi d'origine de sortir avec 1, mais si le code de sortie a déjà été fixée à autre chose, cela va mettre un terme à cette valeur à la place. La première chose Halt
n'est définie la variable globale ExitCode
, de sorte que votre code ne devrait pas avoir besoin d'autres changements (bien que je choisirais un autre nom pour la variable Exitcode
). Votre appel à Halt
fixera la variable globale ExitCode
et procéder ensuite à arrêter le programme. Le gestionnaire d'exception remarquerez que ExitCode
est déjà défini et Halt
re appel à cette valeur au lieu de 1.