ScienceAmateur
ScienceAmateur

Reputation: 531

how to eliminate extraneous console output after ctrl-c in Windows?

When pressing Ctrl-c there is almost always additional output. I'd like to ensure that after receiving the Ctrl-c the program doesn't show anything other than possibly "^C".

I found what is mostly the same question but, it was for Linux and my attempts to "port" the solution from Linux to Windows have not succeeded.

At this point, I'm out of things to try and can use some help, which I will definitely appreciate. Thank you.

The short example program below suffers from that problem.

{$APPTYPE        CONSOLE}

program _SetConsoleCtrlHandler;

uses
  Windows,
  SysUtils
  ;

function CtrlHandler(CtrlType : DWORD) : BOOL; stdcall;
begin
  result := FALSE;

  case CtrlType of
    CTRL_C_EVENT,
    CTRL_BREAK_EVENT:
    begin
      result := TRUE;

      ExitProcess(7);
    end;
  end;
end;

var
  s : shortstring;

begin
  SetConsoleCtrlHandler(@CtrlHandler, TRUE);

  while TRUE do
  begin
    write('press <ctrl-c> to end this program : ');
    readln(s);
  end;
end.

Upvotes: 2

Views: 450

Answers (1)

Allen Drennan
Allen Drennan

Reputation: 291

The way I usually do this is to have a separate unit that is signaled and a simple wait, like the following. In the main console project you call WaitForCtrlC instead of Readln(). You could also use a TEvent and wait on the event instead of looping, like I show in this example:

uses
  {$IFDEF LINUX}
  Posix.Signal,
  {$ENDIF}
  {$IFDEF MSWINDOWS}
  Windows,
  {$ENDIF}
  SysUtils;

procedure WaitForCtrlC;

implementation

var
  Control_C: Boolean = False;

{$IFDEF MSWINDOWS}
function ConsoleCtrlHandler(dwCtrlType: DWORD): BOOL; stdcall;
begin
  if (dwCtrlType = CTRL_C_EVENT) then
    Control_C := True;
  Result := True;
end;
{$ENDIF}

{$IFDEF LINUX}
var
  sigIntHandler: sigaction_t;

procedure SigHandler(SigNum: Integer); cdecl;
begin
  Control_C := True;
end;
{$ENDIF}

procedure WaitForCtrlC;
begin
  while not Control_C do
    Sleep(25);
end;

initialization
  {$IFDEF MSWINDOWS}
  Windows.SetConsoleCtrlHandler(@ConsoleCtrlHandler, True);
  {$ENDIF}
  {$IFDEF LINUX}
  sigIntHandler._u.sa_handler := @SigHandler;
  sigemptyset(sigIntHandler.sa_mask);
  sigIntHandler.sa_flags := 0;
  sigaction(SIGINT, @sigIntHandler, nil);
  {$ENDIF}

Upvotes: 2

Related Questions