2009-06-16 5 views

risposta

17

Da Windows API (MSDN):

BOOL WINAPI SetConsoleCtrlHandler(
    PHANDLER_ROUTINE HandlerRoutine, // address of handler function 
    BOOL Add // handler to add or remove 
    ); 

funzione A HandlerRoutine è una funzione che un processo di console specifica per gestire segnali di controllo ricevuti dal processo. La funzione può avere qualsiasi nome.

BOOL WINAPI HandlerRoutine(
    DWORD dwCtrlType // control signal type 
    ); 

Nel Delphi la routine di gestione dovrebbe essere come:

function console_handler(dwCtrlType: DWORD): BOOL; stdcall; 
begin 
    // Avoid terminating with Ctrl+C 
    if ( CTRL_C_EVENT = dwCtrlType ) then 
    result := TRUE 
    else 
    result := FALSE; 
end; 
+0

Ok, questo dimostra come posso disabilitare Ctrl + C - vorrei chiarire la mia domanda: come faccio a eseguire un arresto applicazione pulito dopo il rilevamento di Ctrl + C? – mjn

+2

Oh, capisco. Se intrappoli il Ctrl + C, come il mio esempio, puoi impostare una sorta di 'flag' e terminare * normalmente * ogni volta che vuoi. –

+0

Ho appena ricordato la "pausa: = falso;" che ho usato per inserire i miei programmi Turbo Pascal per disabilitare Ctrl-Break. Ah, nostalgia ... –

2

ho scritto un piccolo programma per mostrare come fermare correttamente un'attività in background. Speriamo che sia più chiaro.

il contenuto del file ThreadConsoleApplication.dpr:

program ThreadConsoleApplication; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils, 
    Windows, 
    Classes; 

type 
    { ** 
    * Classe TQueueReaderTestApplication 
    * } 
    TThreadConsoleApplication = class(TThread) 
    public 
    procedure Execute; override; 

    constructor Create; virtual; 
    destructor Destroy; override; 

    class function getInstance: TThreadConsoleApplication; 
    end; 

function TThreadConsoleApplication_consoleCtrlHandler(dwCtrlType: DWORD): BOOL; 
    stdcall; forward; 

{ ** 
    * Classe TQueueReaderTestApplication 
    * } 

constructor TThreadConsoleApplication.Create; 
begin 
    inherited Create(True { CreateSuspended }); 
    Windows.setConsoleCtrlHandler(@TThreadConsoleApplication_consoleCtrlHandler, 
    True { add }); 
end; 

var 
    threadConsoleApplicationInstance: TThreadConsoleApplication = nil; 

destructor TThreadConsoleApplication.Destroy; 
begin 
    threadConsoleApplicationInstance := nil; 
    inherited; 
end; 

procedure TThreadConsoleApplication.Execute; 
begin 
    System.Writeln('[TThreadConsoleApplication.Execute] begin'); 
    try 
    while not Terminated do 
    begin 
     System.Writeln('[TThreadConsoleApplication.Execute] running ...'); 
     Windows.Sleep(1000 { dwMilliseconds }); 
    end; 
    finally 
    System.Writeln('[TThreadConsoleApplication.Execute] end'); 
    end; 
end; 

class function TThreadConsoleApplication.getInstance: TThreadConsoleApplication; 
begin 
    if nil = threadConsoleApplicationInstance then 
    begin 
    threadConsoleApplicationInstance := TThreadConsoleApplication.Create; 
    end; 
    Result := threadConsoleApplicationInstance; 
end; 

function TThreadConsoleApplication_consoleCtrlHandler(dwCtrlType: DWORD): BOOL; 
begin 
    Result := False; 
    if Windows.CTRL_C_EVENT = dwCtrlType then 
    begin 
    TThreadConsoleApplication.getInstance.Terminate; 
    Result := True; 
    end; 
end; 

var 
    thread: TThread; 

begin 
    System.Writeln('[program] begin'); 
    try 
    thread := nil; 
    try 
     thread := TThreadConsoleApplication.getInstance; 
     thread.Resume; 
     System.Writeln('[program] press a CTRL+C to stop running'); 
     thread.WaitFor; 
    finally 
     thread.Free; 
    end; 
    System.Writeln('[program] end'); 
    except 
    on E: Exception do 
    begin 
     System.Writeln(System.ErrOutput, '[program] end with error'); 
     System.Writeln(System.ErrOutput, E.ClassName, ': ', E.Message); 
    end; 
    end; 
    System.Writeln('[program] press a key to quit'); 
    System.Readln; 

end.