2009-06-16 11 views

Respuesta

17

De API de Windows (MSDN):

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

función A HandlerRoutine es una función que un proceso de consola especifica para manejar señales de control recibidas por el proceso. La función puede tener cualquier nombre.

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

En el Delphi la rutina de controlador debería ser como:

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, esto demuestra cómo puedo desactivar Ctrl + C - Debo aclarar mi pregunta: ¿Cómo se realiza un cierre aplicación limpia después de detectar Ctrl + C? – mjn

+2

Oh, ya veo. Si atrapas la Ctrl + C, como mi ejemplo, puedes establecer un tipo de 'bandera' y terminar * normalmente * cuando lo desees. –

+0

Acabo de recordar el "break: = false;" que solía poner en mis programas de Turbo Pascal para deshabilitar Ctrl-Break. Ah, nostalgia ... –

2

me escribió un pequeño programa que le muestre cómo detener adecuadamente una tarea de fondo. Afortunadamente es más claro.

contenido del archivo 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. 
Cuestiones relacionadas