Windows中如何在ctrl-c之后消除多余的控制台输出?

时间:2019-03-28 14:14:07

标签: windows delphi winapi windows-console

按Ctrl-c时,几乎总是有附加输出。我想确保在收到Ctrl-c之后,该程序不会显示“ ^ C”以外的任何内容。

我发现了几乎相同的问题,但这是针对Linux的,我尝试将解决方案从Linux“移植”到Windows的尝试均未成功。

在这一点上,我没有什么可以尝试的,可以使用一些帮助,我将不胜感激。谢谢。

下面的简短示例程序遇到了这个问题。

{$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.

1 个答案:

答案 0 :(得分:2)

我通常这样做的方法是拥有一个单独的信号单元并进行简单的等待,如下所示。在主控制台项目中,您调用WaitForCtrlC而不是Readln()。您也可以使用TEvent并等待事件而不是循环,如本例所示:

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}