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?
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.
(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
Hm, i think this happens because the child-process (admin.exe
) uses a few threads...
But how to solve it?
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");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With