How to detect if Console.In (stdin) has been redirected?
You can find out by p/invoking the Windows FileType() API function. Here's a helper class:
using System;
using System.Runtime.InteropServices;
public static class ConsoleEx {
public static bool IsOutputRedirected {
get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdout)); }
}
public static bool IsInputRedirected {
get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stdin)); }
}
public static bool IsErrorRedirected {
get { return FileType.Char != GetFileType(GetStdHandle(StdHandle.Stderr)); }
}
// P/Invoke:
private enum FileType { Unknown, Disk, Char, Pipe };
private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };
[DllImport("kernel32.dll")]
private static extern FileType GetFileType(IntPtr hdl);
[DllImport("kernel32.dll")]
private static extern IntPtr GetStdHandle(StdHandle std);
}
Usage:
bool inputRedirected = ConsoleEx.IsInputRedirected;
UPDATE: these methods were added to the Console class in .NET 4.5. Without attribution I might add :( Simply use the corresponding method instead of this helper class.
https://msdn.microsoft.com/en-us/library/system.console.isoutputredirected.aspx
https://msdn.microsoft.com/en-us/library/system.console.isinputredirected.aspx
https://msdn.microsoft.com/en-us/library/system.console.iserrorredirected.aspx
Is there any method to detect whether STDIN has been redirected within VBscript?
In short, no, but ...
I've tested everything i could think of and have not found a reasonable way to do it.
None of the properties/methods exposed by the TextStream wrappers retrieved with WScript.StdIn
or fso.GetStdStream
give enough information to determine if the input is redirected/piped.
Trying to obtain information from the behaviour/environment of a spawned process (how to create the executable is other story) is also unlikely to be useful because
WshShell.Execute
always spawns the process with its input and output handles redirectedWshShell.Run
creates a new process that does not inherit the handles of the current oneShell.Application.ShellExecute
has the same problem asWshShell.Run
So, none of these methods allow the spawned process to inherit the handles of the current process to check if they are redirected or not.
Using WMI to retrieve information from the running process does not return anything usable (well, HandleCount
property for the process differs when there is a redirection, but it is not reliable)
So, not being able to determine from vbs code if there is a redirection, the remaining options are
Don't detect it: If the piped input must be present, behave as the
more
command and in all cases try to retrieve itIndicate it: If the pipe input is not always required, use an argument to determine if the stdin stream needs to be read.
In my case, I usually use a single slash /
as argument (for coherence with some of the findstr
arguments that also use a slash to indicate stdin input). Then in the vbs code
If WScript.Arguments.Named.Exists("") Then
' here the stdin read part
End If
- Check before: Determine if there is redirection before starting the script. A wrapper
.cmd
is needed, but with some tricks both files (.cmd
and.vbs
) can be combined into one
To be saved as .cmd
<?xml : version="1.0" encoding="UTF-8" ?> ^<!------------------------- cmd ----
@echo off
setlocal enableextensions disabledelayedexpansion
timeout 1 >nul 2>nul && set "arg=" || set "arg=/"
endlocal & cscript //nologo "%~f0?.wsf" //job:mainJob %arg% %*
exit /b
---------------------------------------------------------------------- wsf --->
<package>
<job id="mainJob">
<script language="VBScript"><![CDATA[
If WScript.Arguments.Named.Exists("") Then
Do Until WScript.StdIn.AtEndOfStream
WScript.StdOut.WriteLine WScript.StdIn.ReadLine
Loop
Else
WScript.StdOut.WriteLine "Input is not redirected"
End If
]]></script>
</job>
</package>
It is a .wsf
file stored inside a .cmd
. The batch part determines if the input is redirected (timeout
command fails to get a console handle on redirected input) and pass the argument to the script part.
Then, the process can be invoked as
< inputfile.txt scriptwrapper.cmd input redirected
type inputfile.txt | scriptwrapper.cmd input piped
scriptwapper.cmd no redirection
While this is a convenient way to handle it, the invocation of the .wsf
part from the .cmd
, while being stable and working without problems, relies in an undocumented behaviour of the script host / cmd combination.
Of course you can do the same but with two separate files. Not as clean, but the behaviour is documented.
How can I determine whether Console.Out has been redirected to a file?
p/invoke GetFileType(GetStdHandle(STD_OUTPUT_HANDLE))
, or call an innocuous console function like GetConsoleScreenBufferInfo
to check for invalid handle error. If you want to know about standard error, use STD_ERROR_HANDLE
. I believe you can even compare handles returned by GetStdHandle(STD_OUTPUT_HANDLE)
and GetStdHandle(STD_ERROR_HANDLE)
to detect stuff like 2>&1
.
How do I detect if stdin or stdout is redirected in FreePascal under Windows?
Use
GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
for stdout. It should be obvious what to do for stdin.
How do I determine if sys.stdin is redirected from a file vs. piped from another process?
You're looking for stat
macros:
import os, stat
mode = os.fstat(0).st_mode
if stat.S_ISFIFO(mode):
print "stdin is piped"
elif stat.S_ISREG(mode):
print "stdin is redirected"
else:
print "stdin is terminal"
Detect redirect standard output to nul
The function you quote, originally by Hans Passant, was added to the console in .NET 4.5 (see Console.IsOutputRedirected et al)
Interestingly enough, the implementation in .NET is capable of detecting a redirect to NUL. It does this by doing an additional check whenever the FileType check yields false:
int mode;
bool success = Win32Native.GetConsoleMode(ioHandle, out mode);
return !success;
If you are on .NET 4.5, simply use the built-in function. If not, duplicating this extra check should solve your problem.
How do I check if my Delphi console app is redirected to a file or pipe?
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.
How to know if std::cin is from redirect?
This answer is based on @JoachimPileborg comment
#include <io.h>
#include <stdio.h>
bool isInputRedirected()
{
return (!(_isatty(_fileno(stdin))))
}
Original source in MSDN
How to tell if stderr has been redirected in Windows?
- Call
GetStdHandle
to get the stderr handle. - Pass that handle to
GetFileType
to find out what type of file it is. - If that returns
FILE_TYPE_CHAR
then stderr could be a console, but callGetConsoleMode
to check. - If
GetConsoleMode
fails then stderr has been redirected to another character device, such as a printer.
Related Topics
Upload and Download a File To/From Ftp Server in C#/.Net
Does Using "New" on a Struct Allocate It on the Heap or Stack
JSON.Net: Force Serialization of All Private Fields and All Fields in Sub-Classes
Wpf Createbitmapsourcefromhbitmap() Memory Leak
Xml Serialization and Namespace Prefixes
How to Check for Nulls in an '==' Operator Overload Without Infinite Recursion
Execute C# Code at Runtime from Code File
Return File in ASP.NET Core Web API
Bidirectional 1 to 1 Dictionary in C#
Httpwebrequest Using Basic Authentication
How to Find the Most Recent File in a Directory Using .Net, and Without Looping
ASP.NET MVC: No Parameterless Constructor Defined for This Object
How to Read an Attribute on a Class at Runtime
How to Write a JSON File in C#
Windows 10 Universal App File/Directory Access