OutputDataReceived does not work with windows git.exe - c#

I do have a strange problem: I try to call git.exe to clone a repository via a small c# console-application->
Process p = new Process();
p.StartInfo.FileName = "path/to/git/git.exe";
p.StartInfo.Arguments = "clone SomeGitRepoWhichRequiresPassword";
p.StartInfo.UseShellExecute = false;
p.EnableRaisingEvents = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardError = true;
p.OutputDataReceived += OutputDataReceived;
p.ErrorDataReceived += ErrorDataReceived;
p.Exited += Exited;
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.WaitForExit();
When I try to clone a Repository which needs user-input (e.g. entering a ssh-password) none of the events is triggered so I cannot react to that input programmaticly. Is there a way to really get ALL command-output?
Thanks!

Why do you want to enter password programatically? You can try to write password in Git repository URL like this:
git clone https://username:password#github.com/username/repository.git

Related

Capture output from Powershell version 2

I am having trouble capturing the output from Powershell version 2.
I use the regular Process class to run the program and handle input and output and everything works great. Working code below:
using (Process p = new Process())
{
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = "powershell";
//p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.OutputDataReceived += (sender, args) => AddRow(args.Data);
p.ErrorDataReceived += (sender, args) => AddRow("ERR: " + args.Data);
p.Start();
ps = p.StandardInput;
p.BeginOutputReadLine();
p.BeginErrorReadLine();
Thread.Sleep(1000);
ps.WriteLine("dir");
Thread.Sleep(100);
while (true)
{
Thread.Sleep(10);
}
}
This version starts powershell and sends "dir" to stdinput of the process and the result is sent back to stdout. I can see the cmd-window but i cant write or see any output there as expected. (I know i can hide it).
But then i add this row:
p.StartInfo.Arguments = "-version 2";
This is to start powershell in version 2 and now it just prints 2 rows that tells me powershell is started and then the connection is lost.
I see in the console window that the cursor is blinking and now i can interact with powershell in the command window since the connection to my process class is lost. When i enter "exit" in the window i am back again to my process.
How can i solve this?
Full code (when using version 2 that is not working) below:
using (Process p = new Process())
{
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = "powershell";
p.StartInfo.Arguments = "-version 2";
//p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.OutputDataReceived += (sender, args) => AddRow(args.Data);
p.ErrorDataReceived += (sender, args) => AddRow("ERR: " + args.Data);
p.Start();
ps = p.StandardInput;
p.BeginOutputReadLine();
p.BeginErrorReadLine();
Thread.Sleep(1000);
ps.WriteLine("dir");
Thread.Sleep(100);
while (true)
{
Thread.Sleep(10);
}
}
I hope someone can help me with this! Thanks for your time!

StreamWrite (Interact) to another Application running within a C# Console App

I am writing a shell in C# using a Console App. Using my Shell I would execute other applications such as ping.exe, takeown.exe etc just like you would with cmd or bash.
I have no problem in redirecting Standard Out from the other process to my Console App. The issue is that I don't know how to redirect StardardIn properly so that I can interact with the running application. I.e say I need to enter "y" to confirm an action using cacls.exe.
Here is my code for StandardOut:
How can I write back to the App?
Process process = new Process();
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = cmd;
process.StartInfo.Arguments = Arguments;
process.OutputDataReceived += new DataReceivedEventHandler(
(s, e) =>
{
Console.WriteLine(e.Data);
}
);
process.ErrorDataReceived += new DataReceivedEventHandler((s, e) => { Console.WriteLine(e.Data); });
process.Start();
process.BeginOutputReadLine();
process.WaitForExit();
You should write back the data to the app by using process.StandardInput.WriteLine(message)
and message should be a string.
You can use Write() or WriteLine()

Reading cmd output real time

I'm writing a program that reads python script output and shows the results in textbox.
Since the script runnning for a long time, I want to be able to see the output every 1 second (or after each line is writen).
Now i can see the output only when the process ends.
Does someone know what is the problem?
snippet of my code:
Process p = new Process();
p.StartInfo.CreateNoWindow = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.OutputDataReceived += new DataReceivedEventHandler (p_OutputDataReceived);
p.ErrorDataReceived += new DataReceivedEventHandler (p_ErrorDataReceived);
p.Exited += new EventHandler (p_Exited);
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.FileName = "python.exe";
p.StartInfo.Arguments = "path " + commandline;
p.Start();
StreamReader s = p.StandardOutput;
String output = s.ReadToEnd();
textBox3.Text = output;
p.WaitForExit();
I'm doing it the following way in my own programs:
private static void startProgram(
string commandLine )
{
var fileName = commandLine;
var arguments = string.Empty;
checkSplitFileName( ref fileName, ref arguments );
var info = new ProcessStartInfo();
info.FileName = fileName;
info.Arguments = arguments;
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
using ( var p = new Process() )
{
p.StartInfo = info;
p.EnableRaisingEvents = true;
p.OutputDataReceived += (s,o) => {
Console.WriteLine(o.Data);
};
p.Start();
p.BeginOutputReadLine();
p.WaitForExit();
}
}
I.e. I'm subscribing to the OutputDataReceived event and calling BeginOutputReadLine method. See also this similar Stack Overflow question.
(The method checkSplitFileName in my above source code can be found here)
I had this same problem running my Python script from C#. The problem is that Python buffers the output from stdout (print()).
You could do one of two things here.
1.
Add the following to your Python script, after every print() line to flush the output.
import sys
print('Hello World!')
sys.stdout.flush()
2.
Run the Python compiler with the -u command line parameter. This way you don't need to add the above flush line after every print.
...
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "python.exe -u path " + commandline;
...
Python, by default, buffers its output.
The way to go is to pass a "-u" command line argument to python.
so if you want to execute say hello.py, you would do :
python.exe -u hello.py
Heres the C# code that works for me.
Process p = new Process();
string op = "";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = "c:\\python27\\python.exe";
StreamReader outputStream = p.StandardOutput;
StreamReader errorStream = p.StandardError;
p.StartInfo.Arguments = #"-u hello.py";
p.Start();
string output = "";
int offset = 0, readBytes = 0;
char[] buffer = new char[512];
do
{
output = outputStream.ReadLine();
if (!string.IsNullOrEmpty(output))
{
txtOutput.AppendText(output);
txtOutput.AppendText(Environment.NewLine);
offset += readBytes;
Application.DoEvents();
}
Thread.Sleep(3);
} while (!p.HasExited);

c# run commands through cmd

I need to execute two commands on the cmd. Despite my research I have not found a workable solution to my problem. First I need to cd to directory and then run an exe in that directory.
using (Process process = new Process())
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.WorkingDirectory = #"C:\Program Files\Blacksmith\bin\apache\bin";
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = #" \c httpd.exe";
// Redirects the standard input so that commands can be sent to the shell.
process.StartInfo.RedirectStandardInput = true;
process.OutputDataReceived += ProcessOutputDataHandler;
process.ErrorDataReceived += ProcessErrorDataHandler;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}
I'm trying to execute httpd.exe through cmd.exe to stop apache from being run as a windows service.
Would this work for you?
using (Process process = new Process())
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = #"C:\Program Files\Blacksmith\bin\apache\bin\httpd.exe";
// Redirects the standard input so that commands can be sent to the shell.
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.OutputDataReceived += ProcessOutputDataHandler;
process.ErrorDataReceived += ProcessErrorDataHandler;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}
Try this
using (Process process = new Process())
{
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.WorkingDirectory = #"C:\Program Files\Blacksmith\bin\apache\bin";
process.StartInfo.FileName = "httpd.exe";
// Redirects the standard input so that commands can be sent to the shell.
process.StartInfo.RedirectStandardInput = true;
process.OutputDataReceived += ProcessOutputDataHandler;
process.ErrorDataReceived += ProcessErrorDataHandler;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}
I think that you might try /c instead of \c

Why does Shellexecute=false break this?

I'm learning C# at the moment for a bit of fun and am trying to make a windows application that has a bit of a gui for running some python commands. Basically, I'm trying to teach myself the guts of running a process and sending commands to it, as well as receiving commands from it.
I have the following code at the moment:
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "C:/Python31/python.exe";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
textBox1.Text = output;
Running python.exe from a command prompt gives some introductory text that I'd like to capture and send to a textbox in the windows form (textBox1). Basically, the goal is to have something that looks like the python console running from the windows app. When I don't set UseShellExecute to false, a console pops up and everything runs fine; however, when I set UseShellExecute to false in order to re-direct the input, all I get is that a console pops up very quickly and closes again.
What am I doing wrong here?
For some reason, you shouldn't use forward slashes when you start the process.
Compare (does not work):
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = "C:/windows/system32/cmd.exe";
p.StartInfo.Arguments = "/c dir" ;
p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
bool f = p.Start();
p.BeginOutputReadLine();
p.WaitForExit();
[...]
static void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(e.Data);
}
to (works as expected):
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = #"C:\windows\system32\cmd.exe";
p.StartInfo.Arguments = "/c dir" ;
p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
bool f = p.Start();
p.BeginOutputReadLine();
p.WaitForExit();
[...]
static void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(e.Data);
}
Python seems to be doing something weird. I wouldn't believe it until I tested it and then did some research. But all of these posts basically seem to have the same exact problem:
https://stackoverflow.com/questions/4106095/capturing-standard-output-from-django-using-c
Python & C#: Is IronPython absolutely necessary?
C# capturing python.exe output and displaying it in textbox
Certain Python commands aren't caught in Stdout

Categories

Resources