11

I have a console app that must disable or enable some operations when output is redirected (externally) to a file or pipe (myapp.exe > Foo.bar)

How I can check if my Delphi console app is redirected to a file or pipe?

menjaraz
  • 7,551
  • 4
  • 41
  • 81
Salvador
  • 16,132
  • 33
  • 143
  • 245
  • possible duplicate of [How to detect if Console.In (stdin) has been redirected?](http://stackoverflow.com/questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected) – David Heffernan Jan 26 '12 at 17:49

2 Answers2

13

you can use the GetStdHandle and GetFileType functions.

first you retrieve the console output handle using the GetStdHandle function and then you can check the type of the handle with the GetFileType function.

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Windows,
  SysUtils;


function ConsoleRedirected: Boolean;
var
  FileType : DWORD;
begin
  FileType:= GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
  Result  := (FileType=FILE_TYPE_PIPE) or (FileType=FILE_TYPE_DISK);
end;


begin
  try
    if ConsoleRedirected then
      Writeln('Hello From File')
    else
      Writeln('Hello Console');
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • 3
    The documentation mentions that `File_Type_Char` is "typically an LPT device or a console," so this method might not tell you when your program's output is being redirected to a printer: `myapp.exe > LPT1`. – Rob Kennedy Jan 26 '12 at 18:01
  • 2
    Indeed, but the op ask specifically for `..is redirected to a file or pipe..` so he can use the `Result := (FileType=FILE_TYPE_PIPE) or (FileType=FILE_TYPE_DISK); ` code which is commented on my answer. – RRUZ Jan 26 '12 at 18:37
  • @RRUZ More likely those were the first two types of redirection that popped into his head. And if that's what you believe then I don't know why you commented out that version. – David Heffernan Jan 26 '12 at 18:45
  • @DavidHeffernan, answer edited (sorry but I had my mind on many projects at once). – RRUZ Jan 26 '12 at 18:54
  • 1
    As usual, @Rob is right on the money. This version will not detect all redirection which is how I interpreted the question. For example `myexe > nul` will result in `FILE_TYPE_CHAR`. Accordingly I will leave my answer here unless somebody can come up with a better way of detecting all forms of redirection. – David Heffernan Jan 26 '12 at 18:54
9

The approach I present here feels hacky but I can't find a better way to detect whether or not the standard output has been redirected away from a screen console. The approach using GetFileType cannot detect all forms of redirection since some redirections are to devices of type FILE_TYPE_CHAR.


Call GetConsoleMode() passing the standard output handle. If GetConsoleMode() fails then your console has been redirected.

program RedirectionDetection;
{$APPTYPE CONSOLE}
uses
  Windows;

function ConsoleRedirected: Boolean;
var
  Mode: DWORD;
begin
  Result := not GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), Mode);
end;

begin
  if ConsoleRedirected then begin
    Writeln('I have been redirected');
  end else begin
    Writeln('I am a console');
    Readln;
  end;
end.
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    what if `GetConsoleMode` fails in console mode due to access rights for example? – kobik Jan 26 '12 at 17:31
  • 2
    @kobik It's game over if you haven't got access to your own console!! – David Heffernan Jan 26 '12 at 17:32
  • 2
    what I'm asking is, if this statement is a fact: "If GetConsoleMode() fails then your console has been redirected". – kobik Jan 26 '12 at 17:35
  • @kobik It's a well known method for detecting console redirection. Your comment about access rights would apply to any other method of course. – David Heffernan Jan 26 '12 at 17:40
  • just to let you know I'm not the down-voter. I just had some doubts about your statement. – kobik Jan 26 '12 at 17:53
  • 2
    I think this should be better: `Result := not GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), Mode) and (GetLastError = ERROR_INVALID_HANDLE);` – kobik Jan 26 '12 at 18:09
  • @kobik I'm going to leave the answer here until someone can come up with a better way to detect all forms of redirection. – David Heffernan Jan 26 '12 at 18:57