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 redirect stdin
/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 write uptime
, 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 read stdout
/err
and write to stdin
.
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? The admin.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 the dummy.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?