Redirecting standard input/output/error streams with .NET's Process class
The problem could be because of you are using Readline
, where the data are output from admin.exe
application are sequentially and not in new lines.., try to use Read
instead, and build the desirable string from it..
Also you don't have to use Environment.NewLine
to write string followed by new line, use WriteLine
instead, so:
process.StandardInput.WriteLine("uptime");
Stefan Hasler
Updated on June 04, 2022Comments
-
Stefan Hasler almost 2 years
I'm trying to write a wrapper for an interactive console-based application. For this I use C# and the
Process
class. I'm trying to redirectstdin
/out
/err
, but it doesn't work.Example code:
ProcessStartInfo startInfo = new ProcessStartInfo("admin.exe"); startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardError = true; startInfo.RedirectStandardInput = true; startInfo.UseShellExecute = false; Process process = Process.Start(startInfo); process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data); process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data); while (true) { process.StandardInput.Write("uptime" + Environment.NewLine); process.StandardInput.Flush(); Thread.Sleep(1000); } Console.ReadKey();
Nothing happens. But if I start
admin.exe
and writeuptime
, output is printed.All solutions in the internet use
ReadToEnd
, but I can't use this because i have a dynamic communication on which I have to readstdout
/err
and write tostdin
.Has anyone an idea?
Update
I played with the posted zip on the linked thread. And then i tried to create a small 'proof-of-concept'-code:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.IO; using System.Threading; namespace ConsoleApplication3 { class Program { private static void Read(StreamReader reader) { new Thread(() => { while (true) { int current; while ((current = reader.Read()) >= 0) Console.Write((char)current); } }).Start(); } static void Main(string[] args) { ProcessStartInfo startInfo = new ProcessStartInfo(@"cmd.exe"); startInfo.CreateNoWindow = true; startInfo.ErrorDialog = false; startInfo.RedirectStandardError = true; startInfo.RedirectStandardInput = true; startInfo.RedirectStandardOutput = true; startInfo.UseShellExecute = false; startInfo.CreateNoWindow = true; Process process = new Process(); process.StartInfo = startInfo; process.Start(); Read(process.StandardOutput); Read(process.StandardError); while (true) process.StandardInput.WriteLine(Console.ReadLine()); } } }
It works perfectly:-)
But with the
admin.exe
it doesn't work? Theadmin.exe
doesn't use any tricky input-method and it doesn't need an inputed password.I know the
admin.exe
is written in c and compiled with mingw on linux. So i created a small dummy-tool:#include <stdio.h> int main() { int readed; while ((readed = fgetc(stdin)) >= 0) fputc((char)readed, stdout); }
This tool does only echo the inputed text/line. I compiled it with
i586-mingw32msvc-gcc
and copied it to my windows machine. There i used the program on the top of this post to communicate with thedummy.exe
. It doesn't work. No echo is shown. But why?I compiled the dummy-code also with the Microsoft C++ Compiler, same effect.
Update2
(btw: Thanks to Tim Post)
I'm trying and trying. I tried to create a c-Tool, which does the same as my c# tool. I used
_popen
, but the effect was, that the output were shown at the end of the process. Hm, not good.I found this alternative command shell for windows:
https://stackoverflow.com/questions/440269/whats-a-good-alternative-windows-console
http://sourceforge.net/projects/console/
It seems to work. It gets the stdout/err in realtime, can redirect the stdin and
admin.exe
works. And it is opensource. May be i'll find the solution inside the C++-Code.I'm not well in C++, so it's hard, but i'll try it. May be i have to write a "clear" redirect-wrapper in C/C++ and use it in C#.
If someone has an idea please say it, because the other way can be very hard (for me^^):-)
Thanks.
best regards
Update 3
Hm, i think this happens because the child-process (
admin.exe
) uses a few threads... But how to solve it? -
user1703401 over 12 yearsThere is no ReadLine() in the snippet.
-
Jalal Said over 12 yearsYes, I was referring to
BeginOutputReadLine
and so thee.Data
inOutputDataReceived
will just read lines, I think the same also apply toBeginErrorReadLine
here.. -
Kiquenet over 9 yearsYou need to set UseShellExecute to true for the Verb to be respected and it must be set to 'false' to redirect standard output. You can't do both. I'm pretty sure Windows also won't allow you to redirect standard input/output/error across the admin/non-admin security boundary. You'll have to find a different way to get output from the program running as admin - Reference: stackoverflow.com/a/8690661