2009-06-16 8 views

Répondre

17

De l'API Windows (MSDN):

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

Une fonction HandlerRoutine est une fonction qu'un processus de console spécifie pour traiter des signaux de commande reçus par le processus. La fonction peut avoir n'importe quel nom.

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

Dans Delphi la routine de gestionnaire doit être comme:

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, cela montre comment je peux désactiver les touches Ctrl + C - Je dois préciser ma question: comment puis-je effectuer un arrêt d'application propre après la détection Ctrl + C? – mjn

+2

Oh, je vois. Si vous piègez le Ctrl + C, comme mon exemple, vous pouvez définir une sorte de 'drapeau' et terminer * normalement * quand vous le voulez. –

+0

Je viens de me souvenir du "break: = false". que j'avais l'habitude de mettre dans mes programmes Turbo Pascal pour désactiver Ctrl-Break. Ah, la nostalgie ... –

2

j'ai écrit un petit programme pour vous montrer comment arrêter correctement une tâche d'arrière-plan. J'espère que c'est plus clair.

Contenu du fichier 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. 
Questions connexes