C# Console receive input with pipe - c#

I know how to program Console application with parameters, example : myProgram.exe param1 param2.
My question is, how can I make my program works with |, example : echo "word" | myProgram.exe?

You need to use Console.Read() and Console.ReadLine() as if you were reading user input. Pipes replace user input transparently. You can't use both easily (although I'm sure it's quite possible...).
Edit:
A simple cat style program:
class Program
{
static void Main(string[] args)
{
string s;
while ((s = Console.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
}
And when run, as expected, the output:
C:\...\ConsoleApplication1\bin\Debug>echo "Foo bar baz" | ConsoleApplication1.exe
"Foo bar baz"
C:\...\ConsoleApplication1\bin\Debug>

The following will not suspend the application for input and works when data is or is not piped. A bit of a hack; and due to the error catching, performance could lack when numerous piped calls are made but... easy.
public static void Main(String[] args)
{
String pipedText = "";
bool isKeyAvailable;
try
{
isKeyAvailable = System.Console.KeyAvailable;
}
catch (InvalidOperationException expected)
{
pipedText = System.Console.In.ReadToEnd();
}
//do something with pipedText or the args
}

in .NET 4.5 it's
if (Console.IsInputRedirected)
{
using(stream s = Console.OpenStandardInput())
{
...

This is the way to do it:
static void Main(string[] args)
{
Console.SetIn(new StreamReader(Console.OpenStandardInput(8192))); // This will allow input >256 chars
while (Console.In.Peek() != -1)
{
string input = Console.In.ReadLine();
Console.WriteLine("Data read was " + input);
}
}
This allows two usage methods. Read from standard input:
C:\test>myProgram.exe
hello
Data read was hello
or read from piped input:
C:\test>echo hello | myProgram.exe
Data read was hello

Here is another alternate solution that was put together from the other solutions plus a peek().
Without the Peek() I was experiencing that the app would not return without ctrl-c at the end when doing "type t.txt | prog.exe" where t.txt is a multi-line file. But just "prog.exe" or "echo hi | prog.exe" worked fine.
this code is meant to only process piped input.
static int Main(string[] args)
{
// if nothing is being piped in, then exit
if (!IsPipedInput())
return 0;
while (Console.In.Peek() != -1)
{
string input = Console.In.ReadLine();
Console.WriteLine(input);
}
return 0;
}
private static bool IsPipedInput()
{
try
{
bool isKey = Console.KeyAvailable;
return false;
}
catch
{
return true;
}
}

This will also work for
c:\MyApp.exe < input.txt
I had to use a StringBuilder to manipulate the inputs captured from Stdin:
public static void Main()
{
List<string> salesLines = new List<string>();
Console.InputEncoding = Encoding.UTF8;
using (StreamReader reader = new StreamReader(Console.OpenStandardInput(), Console.InputEncoding))
{
string stdin;
do
{
StringBuilder stdinBuilder = new StringBuilder();
stdin = reader.ReadLine();
stdinBuilder.Append(stdin);
var lineIn = stdin;
if (stdinBuilder.ToString().Trim() != "")
{
salesLines.Add(stdinBuilder.ToString().Trim());
}
} while (stdin != null);
}
}

Console.In is a reference to a TextReader wrapped around the standard input stream. When piping large amounts of data to your program, it might be easier to work with that way.

there is a problem with supplied example.
while ((s = Console.ReadLine()) != null)
will stuck waiting for input if program was launched without piped data. so user has to manually press any key to exit program.

Related

Is there a way to Check if something is written except waiting till something is written with "Console.ReadLine()"

I'm doing a TCP Messenger Programm ATM with TCPClient and TCPListener. Everything is working fine. I've had both of these in separate programs and now I'm basically trying to make it one Program. I'm stuck with the fact that it is always WAITING till I have something written to send it before it goes to checking the receive. I'm new to C# and learning. So I need a way to check "is something written? If no, then skip this" basically a bool to ask if something is written.
I've tried to make it like "if the line in storage right now is the same as the was the last time, skip it" so it doesnt stuck infinitly in the Send sector of the program. But still it ALWAYS waits until I wrote something before it even checks/ skips it.
This is the write and send loop code:
nachricht = Console.ReadLine();
if (nachrichtcheck != nachricht)
{
Console.WriteLine("test1");
TcpClient clientnachricht = new TcpClient(zielip, port);
NetworkStream streamnachricht = clientnachricht.GetStream();
sendnachricht = Encoding.ASCII.GetBytes(nachricht);
streamnachricht.Write(sendnachricht, 0, sendnachricht.Length);
streamnachricht.Close();
clientnachricht.Close();
nachrichtcheck = nachricht;
Console.WriteLine("test2");
}
else
{
if (empfangstream.CanRead)
{
Console.WriteLine("test3");
byte[] receivedBuffer2 = new byte[100];
NetworkStream stream = empfangclient.GetStream();
stream.Read(receivedBuffer, 0, receivedBuffer.Length);
StringBuilder msg2 = new StringBuilder();
foreach (byte b in receivedBuffer)
{
if (b.Equals(00))
{
break;
}
else
msg2.Append(Convert.ToChar(b).ToString());
}
Console.WriteLine("test4");
empfangscheck2 = msg2.ToString();
if (empfangscheck2 != empfangscheck)
{
Console.WriteLine(msg2.ToString());
empfangscheck = msg2.ToString();
Console.WriteLine("receive");
}
}
}
So if someone can help me just getting a way to get a bool to check if something is written -> then use it. Except of wait until something is written -> use it it would help me miles.
I've got an alternative to solve your problem. You can use a thread to wait for an user input instead of your actual code.
(I've also considered your german language)
Code Example:
using System;
using System.Threading;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
string nachricht = "";
double AndereTätigkeitBeweis = 0;
Thread NachrichtenEinleser = new Thread(()=> {
Console.Write("Gib diene zu sendende Nachricht ein: ");//Type in the message you'd like to send
nachricht = Console.ReadLine();//Read the user Input without stopping the actual code because it's another process
});
NachrichtenEinleser.Start();
//do somewhat activity until you get a user input
while (nachricht == ""){
AndereTätigkeitBeweis++;
}
//Write out the user input
Console.WriteLine($"User Input: {nachricht}|AndereTätigkeitBeweis: {AndereTätigkeitBeweis}");
Console.ReadLine();
}
}
}
Output example:
Gib diene zu sendende Nachricht ein: hallo
User Input: hallo|AndereTätigkeitBeweis: 560075647
Hope this helps.

How to interact with data piped to console application similar to the LESS program [duplicate]

I know how to program Console application with parameters, example : myProgram.exe param1 param2.
My question is, how can I make my program works with |, example : echo "word" | myProgram.exe?
You need to use Console.Read() and Console.ReadLine() as if you were reading user input. Pipes replace user input transparently. You can't use both easily (although I'm sure it's quite possible...).
Edit:
A simple cat style program:
class Program
{
static void Main(string[] args)
{
string s;
while ((s = Console.ReadLine()) != null)
{
Console.WriteLine(s);
}
}
}
And when run, as expected, the output:
C:\...\ConsoleApplication1\bin\Debug>echo "Foo bar baz" | ConsoleApplication1.exe
"Foo bar baz"
C:\...\ConsoleApplication1\bin\Debug>
The following will not suspend the application for input and works when data is or is not piped. A bit of a hack; and due to the error catching, performance could lack when numerous piped calls are made but... easy.
public static void Main(String[] args)
{
String pipedText = "";
bool isKeyAvailable;
try
{
isKeyAvailable = System.Console.KeyAvailable;
}
catch (InvalidOperationException expected)
{
pipedText = System.Console.In.ReadToEnd();
}
//do something with pipedText or the args
}
in .NET 4.5 it's
if (Console.IsInputRedirected)
{
using(stream s = Console.OpenStandardInput())
{
...
This is the way to do it:
static void Main(string[] args)
{
Console.SetIn(new StreamReader(Console.OpenStandardInput(8192))); // This will allow input >256 chars
while (Console.In.Peek() != -1)
{
string input = Console.In.ReadLine();
Console.WriteLine("Data read was " + input);
}
}
This allows two usage methods. Read from standard input:
C:\test>myProgram.exe
hello
Data read was hello
or read from piped input:
C:\test>echo hello | myProgram.exe
Data read was hello
Here is another alternate solution that was put together from the other solutions plus a peek().
Without the Peek() I was experiencing that the app would not return without ctrl-c at the end when doing "type t.txt | prog.exe" where t.txt is a multi-line file. But just "prog.exe" or "echo hi | prog.exe" worked fine.
this code is meant to only process piped input.
static int Main(string[] args)
{
// if nothing is being piped in, then exit
if (!IsPipedInput())
return 0;
while (Console.In.Peek() != -1)
{
string input = Console.In.ReadLine();
Console.WriteLine(input);
}
return 0;
}
private static bool IsPipedInput()
{
try
{
bool isKey = Console.KeyAvailable;
return false;
}
catch
{
return true;
}
}
This will also work for
c:\MyApp.exe < input.txt
I had to use a StringBuilder to manipulate the inputs captured from Stdin:
public static void Main()
{
List<string> salesLines = new List<string>();
Console.InputEncoding = Encoding.UTF8;
using (StreamReader reader = new StreamReader(Console.OpenStandardInput(), Console.InputEncoding))
{
string stdin;
do
{
StringBuilder stdinBuilder = new StringBuilder();
stdin = reader.ReadLine();
stdinBuilder.Append(stdin);
var lineIn = stdin;
if (stdinBuilder.ToString().Trim() != "")
{
salesLines.Add(stdinBuilder.ToString().Trim());
}
} while (stdin != null);
}
}
Console.In is a reference to a TextReader wrapped around the standard input stream. When piping large amounts of data to your program, it might be easier to work with that way.
there is a problem with supplied example.
while ((s = Console.ReadLine()) != null)
will stuck waiting for input if program was launched without piped data. so user has to manually press any key to exit program.

running multiple threads with continous value returns (ping program)

good day
I have taken up a project that as a bases needs insernt a command into cmd "ping x.x.x.x -t" and the program needs to return the output until a specified parameter
I am considering threads as my unterstanding in multithreading is limited, I am unable to continue without guidance
my ping class which recieves a string ip, adds it to a precompiled command string, etc.
I am aware of the built in ping class for this use, but I would prefer the "longer" method since i would gain valueble information/experience from this
main object class: ping
class ping
{
Process proc;
ProcessStartInfo psi;
string ip_address;
bool bStop = false;
public ping(string ip)
{
ip_address = ip;
}
public void StartPing()
{
string cmdInput;
psi = new ProcessStartInfo(Environment.GetEnvironmentVariable("COMSPEC"));
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
proc = Process.Start(psi);
proc.StandardInput.WriteLine("ping " + ip_address + " -t");
cmdInput = proc.StandardOutput.ReadLine();
cmdInput = proc.StandardOutput.ReadLine();
cmdInput = proc.StandardOutput.ReadLine();
cmdInput = proc.StandardOutput.ReadLine();
cmdInput = proc.StandardOutput.ReadLine();
cmdInput = proc.StandardOutput.ReadLine();
while (bStop == false)
{
cmdInput = proc.StandardOutput.ReadLine();
Console.WriteLine(returnPing(cmdInput));
}
proc.Close();
}
private string returnPing(string cmdInput)
{
int start, end;
string ping;
if (cmdInput.IndexOf("Reply") != -1 && cmdInput.IndexOf("time") != -1)
{
start = cmdInput.IndexOf("time=") + 5;
end = cmdInput.IndexOf("ms");
ping = cmdInput.Substring(start, end - start);
return ping;
}
else return "-1";
}
and thread_handler class, which manages mutliple instances of the ping method, please not the console.writeline is a temporary output which I will change in the future
class thread_handler
{
string[] ipList;
private IList<Thread> threadList;
public thread_handler(string[] ip)
{
ipList = ip;
threadList = new List<Thread>();
createThreads();
}
private void createThreads()
{
foreach (string item in ipList)
{
ping NewPing = new ping(item);
Thread newPingThread = new Thread(NewPing.StartPing);
newPingThread.IsBackground = true;
newPingThread.Name = string.Format("{0}", item);
threadList.Add(newPingThread);
}
startAllThreads();
}
private void startAllThreads()
{
foreach (Thread item in threadList)
{
item.Start();
}
}
}
Program
class Program
{
static string[] ipList;
static void Main(string[] args)
{
ipList = new String[3];
readData();
sendData();
}
private static void sendData()
{
thread_handler thIp = new thread_handler(ipList);
}
private static void readData()
{
//use sll with name defintions and ip address's with metadata
ipList[0] = "10.0.0.2";
ipList[1] = "telkom_exchange";
ipList[2] = "goo.gl";
}
The aim of this program is (with gui changes in future) for a simple console with respective dimensions to constantly ping certain ip address's (we have ban infrastructure, thus program is for informative purposes), constantly updating on every ping reply
I do not want anyone to finish this program, I simply require assistance with running multiple instances (or maybe "threads") of this pinging, thus
each thread as it runs the "StartPing()" method, it should return an output, e.g. simply output the ping into the console, but it doesnt...
Output:
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
then hangs
The way you read from the child process is not right. This is a surprisingly complicated task. I don't know why you are getting this specific error message but it sounds like it has to do with process standard output redirection. For example you have not redirected standard error.
I suggest you use one of the top voted snippets of stack overflow, to be found by: site:stackoverflow.com process RedirectStandardOutput. There are hundreds of such questions. Most solutions are subtly wrong.
This is a good checklist.
You should use the ping class to execute a ping. This class allows you to control many details.
The call to ping.exe with Process.Start() involves way too much overhead and complicates things (as you experienced in your try)
As simple as it is, redirecting standard input and output did it, with a tweak or two, voila

Output message to Console window if command line parameters incorrect

Can anyone help me output a message to a console box when my .exe is called with the wrong parameters?
Yesterday, some very kind people helped me work out how to call my app without a UI
Here is the thread
command line to make winforms run without UI
So, I have told my app to respond to "/silent archive=true transcode=true" and runs without a UI. Great!
Is it possible to output a message to the command window if they get the command incorrect?
as in "Parameters must be specified like this: /silent archive=true transcode=true"
I have tried this but nothing displays in the dos window..
static void Main(string[] args)
{
if (args.Length > 0)
{
if (args[0] == "/silent")
{
bool archive = false;
bool transcode = false;
try
{
if (args[1] == "transcode=true") { transcode = true; };
if (args[2] == "archive=true") { archive = true; };
Citrix_API_Tool.Engine.DownloadFiles(transcode, archive);
}
catch
{
Console.Write ("Hello");
Console.ReadLine();
return;
}
}
}
else
internal sealed class Program
{
[DllImport("kernel32.dll")]
private static extern bool AttachConsole(int dwProcessId);
private const int ATTACH_PARENT_PROCESS = -1;
[STAThread]
private static void Main(string[] args)
{
if(false)//This would be the run-silent check.
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
try
{
throw new Exception("Always throw, as this tests exception handling.");
}
catch(Exception e)
{
if(AttachConsole(ATTACH_PARENT_PROCESS))
{
//Note, we write to Console.Error, not Console.Out
//Partly because that's what error is for.
//Mainly so if our output were being redirected into a file,
//We'd write to console instead of there.
//Likewise, if error is redirected to some logger or something
//That's where we should write.
Console.Error.WriteLine();//Write blank line because of issue described below
Console.Error.WriteLine(e.Message);
Console.Error.WriteLine();//Write blank line because of issue described below
}
else
{
//Failed to attach - not opened from console, or console closed.
//do something else.
}
}
}
}
A problem is that the console would have already returned to taking input from the user. Hence you really want to try to have your exception as fast as you can if you're going to have it, so a fast validation check rather than an exception that might happen down the line, is preferable.

Java's waitFor() method seems to hang

I have written a simple routine in .Net that I need to call from Java and check the exit value. For some reason when called from Java, waitFor never ends. This is in spite of the fact that when called from command prompt .Net routine ends quickly and when called from test.bat it properly returns -1. Anyone has any idea what the problem is?
Here is Java code:
public static int runOnceWait(String[] cmdarray) throws IOException, InterruptedException
{
Process p;
p = Runtime.getRuntime().exec(cmdarray);
int res = p.waitFor();
p.destroy();
return res;
}
/**
* #param args
* #throws InterruptedException
* #throws IOException
*/
public static void main(String[] args) throws IOException, InterruptedException
{
String [] cmd = new String[2];
cmd[0]=signer;
cmd[1]=fileLocation;
System.out.println ("\"" + cmd[0] + "\" \"" + cmd[1] + "\"");
System.out.println (runOnceWait(cmd));
}
Here's C# code:
static int Main(string[] args)
{
if (args.Length != 1 && args.Length != 2)
{
Console.WriteLine("Use: ");
Console.WriteLine("DocumentSigner.exe source");
Console.WriteLine(" or");
Console.WriteLine("DocumentSigner.exe source, destination");
return -100;
}
string destination = null;
try
{
if (args.Length == 1) destination = Sign(args[0]);
else destination = Sign(args[0], args[1]);
Console.WriteLine("Document signed and saved as " + destination);
}
catch (Exception e)
{
Console.WriteLine(e);
return -1;
}
return 0;
}
For testing purposes I even wrote a .bat file which behaves as expected, i.e. returns ERRORLEVEL of -1.
Here's .bat file:
#echo off
rem test.bat
"DocumentSigner.exe" "{5E3C1967-A26E-4FC5-A6A8-3F358F388A3D}.pdf"
#if "%ERRORLEVEL%" == "0" goto good
:fail
echo Execution Failed
echo return value = %ERRORLEVEL%
goto end
:good
echo Execution succeeded
echo Return value = %ERRORLEVEL%
goto end
:end
From the API reference of java.lang.Process (emphasis mine):
By default, the created subprocess does not have its own terminal or
console. All its standard I/O (i.e. stdin, stdout, stderr) operations
will be redirected to the parent process, where they can be accessed
via the streams obtained using the methods getOutputStream(),
getInputStream(), and getErrorStream(). The parent process uses these
streams to feed input to and get output from the subprocess. Because
some native platforms only provide limited buffer size for standard
input and output streams, failure to promptly write the input stream
or read the output stream of the subprocess may cause the subprocess
to block, or even deadlock.
I would try to read from java what your c# application is writing with Console.WriteLine(), e.g. doing something like this after your exec()
BufferedReader in = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}

Categories