I am trying to write a shell for an interactive console application. For this, I use the C # and Process classes. I am trying to redirect stdin / out / err , but it does not work.
Code example:
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 , the output is printed.
All solutions on the Internet use ReadToEnd , but I canโt use it because I have a dynamic link on which I have to read stdout / err and write to stdin .
Does anyone have an idea?
Update
I played with a published zip code in a related topic. And then I tried to create a little "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 great :-)
But admin.exe it not work with admin.exe ? admin.exe does not use any complicated input method and does not need the password entered.
I know admin.exe written in c and compiled from mingw on linux. So, I created a small mannequin tool:
#include <stdio.h> int main() { int readed; while ((readed = fgetc(stdin)) >= 0) fputc((char)readed, stdout); }
This tool only echoes the input of the entered text / line. I compiled it using i586-mingw32msvc-gcc and copied it to my windows machine. There I used the program at the top of this post to communicate with dummy.exe . This does not work. Echo is not displayed. But why?
I compiled the dummy code also with the Microsoft C ++ compiler, the same effect.
Update2
(btw: Thanks Tim Post)
I try and try. I tried to create a c-Tool that does the same thing as my C # tool. I used _popen , but the effect was that the output was shown at the end of the process. Hmm, not good.
I found this alternate command shell for windows:
https://stackoverflow.com/questions/440269/whats-a-good-alternative-windows-console
http://sourceforge.net/projects/console/
It seems to have worked. It gets stdout / err in real time, can redirect stdin and admin.exe works. And it is open source. Perhaps I will find a solution inside C ++ code.
I feel bad in C ++, so it's hard, but I will try. Maybe I need to write a โclearโ overriding shell in C / C ++ and use it in C #.
If anyone has an idea, tell me about it, because the other way can be very difficult (for me ^^) :-)
Thanks.
Best wishes
Update 3
Hm, I think this is because the child process ( admin.exe ) uses multiple threads ... But how to solve it?