2010-08-04 3 views
6

업데이트 : D2007에만 해당하는 것으로 보입니다. 이전 버전에서 작동했던 것처럼 D2010에서 작동합니다.D2007의 예외 블록에서 Halt (n)가있는 오류 코드를 반환하는 방법은 무엇입니까?

내가 좋아하는 우유 공급 처리기 블록에서 잡은 예외의 종류에 따라 종료 코드 반환 싶습니다 : 예외 블록에서 정지 (n)를 호출 불행하게도 D2007에

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. 

, 를 항상 반환 종료 코드 1, Halt()에 전달하는 것과 관계없이 아무리 내가 Halt(1)를 것을 얻을 내가 원하는 것을 종료 코드

procedure ExceptHandler(ExceptObject: TObject; ExceptAddr: Pointer); far; 
begin 
    ShowException(ExceptObject, ExceptAddr); 
    Halt(1); // <= @#$##@#$! 
end; 

을 그리고 :

는 예외 핸들러에서 종료하는 것은 SysUtils.ExceptHandler 전화, 보류 (비 중단) 예외를 지 웁니다의 Finalize를 호출하지 분명히 있기 때문에!

그래서 질문은 :
어떻게 간단하게 제기 된 예외에 따라 원하는 종료 코드를 반환 할 수 있습니다?

+0

, 그것은 참으로 정확한 에러 코드를 반환 않습니다. 예상대로 작동하지 않을 수도있는 ErrorCode를 얻는 데 사용하는 방법이라고 생각합니다. – zz1433

+0

@Aldo. 아니, D2007이야. 똑같은 것은 D2007과 D2010에서 다르게 작동합니다. 마이크가 예상하고보고 한대로 돌아 왔습니다. –

+0

QC (http://qc.embarcadero.com/)에서 큰 보고서를 제출하십시오; D2007 업그레이드가 없을지라도, 알려진 버그를 볼 수 있다는 것이 좋습니다. –

답변

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; 

어쨌든 : it's a bug in D2007, which was fixed in D2010. 정지 (I)를 사용하여

+0

고마워요! +1'AcquireExceptionObject'는 D2007의 해결 방법으로 나를 위해 속임수를 쓰고 있습니다. 정말로 좋은 버그 였어. –

2

사실 ... 그 다음 아래 DOS 상자를 실행, 의도 한대로 난 당신의 코드를 사용

이 ...

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. 

델파이 5에서 컴파일 .... 작동하는 것 같다 XP ... DOS 오류 레벨 0 65535 반향 % ERRORLEVEL %의 범위로 제한됩니다

C:\>test1 
Enter error code: 
111 
EExternal: sdsdkfjh 

C:\>echo %errorlevel% 
111 

C:\> 

참고 오류 수준을 볼 수있는 가장 빠른 방법입니다.

오류 수준 읽기가 오류를 지우는 것을 잊지 마십시오.

+1

D2007에서 더 이상 작동하지 않습니다! 그러나 그것이 일하기 위해 사용되는 것을 확인해 주셔서 감사합니다! 내가 전에 그런 식으로했을 것이라고 확신했다. ;-) –

+1

그리고 D2010에서도 작동한다. 동일한 정확한 코드, errorlevel을 테스트하는 똑같은 방식은 D2010에서 내가 원하는 것을 D5와 함께 제공하지만 D2007에서는 항상 1을 얻습니다! –

2

정리를하지 않고 즉시 프로그램을 중단하고 종료 코드를 반환하려면 ExitProcess을 시도하십시오. ExitProcess 사용에 대한 몇 가지주의 사항은이 기사를 참조하십시오.

+0

+1은 ExitProcess입니다. 현재의 경우에는 너무 가혹하지만 기억해야 할 가치가 있습니다. –

-1

는 내장 된 예외 처리 기능은 당신이 좋아하는 일을하지 않는 경우, 자신의로 대체 : 글로벌 System.ExceptProc 변수에 프로그램이 시작

function ExitCodeExceptHandler(ExceptObject: TObject; ExceptAddr: Pointer); 
begin 
    ShowException(ExceptObject, ExceptAddr); 
    if ExitCode = 0 then 
    ExitCode := 1; 
    Halt(ExitCode); 
end; 

지정 때 :

ExceptProc := @ExitCodeExceptHandler; 

글로벌 ExitCode 변수를 사용하도록 구현했습니다. 여전히 기본값 인 0이면 함수는 1로 끝나는 원래의 Delphi 비헤이비어로 되돌아갑니다. 그러나 종료 코드가 이미 다른 값으로 설정된 경우 대신이 값으로 중단됩니다. 첫 번째 내용은 Halt이고 변수는 ExitCode이고 변수는 Exitcode 변수에 대해 다른 이름을 사용합니다. Halt으로 전화하면 글로벌 ExitCode 변수가 설정되고 프로그램이 종료됩니다. 예외 처리기에서는 ExitCode이 이미 설정되어 있고 Halt을 1 대신 해당 값으로 다시 호출합니다.

+5

아쉽게도 작동하지 않습니다. 먼저, 함수가 아닌 프로 시저 여야하지만, DoneExceptions에 도착할 때 코드는 ExceptProc : = nil'을 재설정하고'if (ExceptObject <> nil)가 아니라 ExceptObject가 EAbort 인 경우 직접 호출합니다. ExceptHandler (ExceptObject, ExceptAddr); ' –

0

는 메모리 누수를 발생 (당신이 볼 수있는 당신은 ReportMemoryLeaksOnShutdown와 FASTMM의 MemoryLeaks 활성화 된 경우 : = TRUE)

그것은 "클린"종료를 사용하는 것이 훨씬 낫다 전에 종료에 ExitCode를 설정을 . 예를 들어 콘솔 응용 프로그램의 메인 섹션에서

은 : 사실 마이크, 아래의 코멘트를 바탕으로

ExitCode:=I; 
exit;