I am trying to retrieve console output of a python script by running that script in c# console application. but I don't know what I am doing wrong as I am not able to read any output. Please help me.
This is my code sample:
Process proc = new Process();
try
{
proc.StartInfo.FileName = "C:\\Program Files\\Python36\\python.exe";
proc.StartInfo.Arguments = "\"E:/Database/Python Scripts/TestFile.py\" \"E:/Database/Testing.db\"";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.CreateNoWindow = true;
proc.EnableRaisingEvents = true;
proc.Start();
while (!proc.StandardOutput.EndOfStream)
{
string line = proc.StandardOutput.ReadLine();
Console.WriteLine("line:" + line);
}
Console.WriteLine("The End");
Console.ReadLine();
}
catch(Exception ex)
{
Console.WriteLine("Error:{0}, Detail: {1}", ex.Message, ex.StackTrace);
Console.ReadLine();
}
finally
{
//Console.ReadLine();
proc.Close();
proc.Dispose();
}
First you need to set proc.StartInfo.RedirectStandardOutput = false; to true
then you need to listen for the output event
proc.StartInfo.FileName = "C:\\Program Files\\Python36\\python.exe";
proc.StartInfo.Arguments = "\"E:/Database/Python Scripts/TestFile.py\" \"E:/Database/Testing.db\"";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.CreateNoWindow = true;
proc.EnableRaisingEvents = true;
proc.OutputDataReceived+= ProcessOutputHandler;
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
private void ProcessOutputHandler(object sender, DataReceivedEventArgs e)
{
//get the data using e.Data
}
You can do the same thing for the ErrorOutput Since they are seperate streams you can get. To listen for error just add an event listener for proc.ErrorDataReceived+= ProcessErrorOutputHandler;
Related
I want to run visual studios command programmatically.I have tried the above code but no help.All I am getting is a command prompt with my project`s directory open.
I have used Execute("VS140COMNTOOLS") as input.
private void Execute(string vsEnvVar) {
var vsInstallPath = Environment.GetEnvironmentVariable(vsEnvVar);
if (Directory.Exists(vsInstallPath)) {
var filePath = vsInstallPath + "vsvars32.bat";
if (File.Exists(filePath)) {
//start vs command process
Process proc = new Process();
var command = Environment.GetEnvironmentVariable("ComSpec");
command = #"" + command + #"";
//var batfile = #"E:\Test\vstest.bat";
var args = string.Format("/S/K \" \"{0}\" \"", filePath);
proc.StartInfo.FileName = command;
proc.StartInfo.Arguments = args;
//proc.StartInfo.RedirectStandardInput = true;
//proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.CreateNoWindow = false;
proc.StartInfo.UseShellExecute = false;
proc.Start();
} else {
Console.WriteLine("File Does not exists " + filePath);
}
}
}
Try this:
private Process Execute(string vsEnvVar)
{
Process process = new Process();
ProcessStartInfo psi = new ProcessStartInfo("cmd.exe");//assume location is in path. Otherwise use ComSpec env variable
psi.CreateNoWindow = true;
psi.UseShellExecute = false;
psi.RedirectStandardError = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.WindowStyle = ProcessWindowStyle.Hidden;
process.StartInfo = psi;
// attach output events
process.ErrorDataReceived += new DataReceivedEventHandler(process_ErrorDataReceived);
process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
process.StartInfo = psi;
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.StandardInput.WriteLine(string.Format("call \"%{0}%vsvars32.bat\""), vsEnvVar);
process.StandardInput.Flush();
return process;
}
Now you can execute any commands by writing to process.StandardInput
process.StandardInput.WriteLine(#"msbuild c:\MySolution.sln /t:Clean");
I am trying to run cmd winsat -drive c programmatically
The code below is only returning "Windows System Assessment Tool" the first line of the output but is not letting the winsat run and return the rest of the output
I am looking for the entire output to be returned shown here
The code I am using is this
public string RunAndOutput(object command)
{
var procStartInfo =
new ProcessStartInfo("winsat", "/c " + "-drive c");
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
var proc = new Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
proc.WaitForExit(); // Wait for everything to finish
return result;
}
You will need to wait for the process to exit using WaitForExit(), like this:
public string RunAndOutput(object command)
{
var procStartInfo =
new ProcessStartInfo("cmd", "/c " + command);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
var proc = new Process();
proc.StartInfo = procStartInfo;
proc.Start();
string result = proc.StandardOutput.ReadToEnd();
proc.WaitForExit(); // Wait for everything to finish
return result;
}
I am creating WinForm application which starts a process with redirection. I am using Async method:
proc = new Process();
proc.StartInfo.FileName = commandLocation + procesName;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.Arguments = arguments;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardInput = true;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.WorkingDirectory = workingDirectory;
proc.StartInfo.CreateNoWindow = true;
proc.OutputDataReceived += (sender, args) => AppendLine(args.Data);
proc.ErrorDataReceived += (sender, args) => AppendLine(args.Data);
proc.Start();
proc.StandardInput.WriteLine(inputText);
proc.BeginOutputReadLine();
while (!proc.HasExited) //Instead of WaitForExit
{
Thread.Sleep(100); //Because of CPU usage
Application.DoEvents();
}
Here is AppendLine method for displaying output to richtextbox:
private void AppendLine(string line)
{
if (richTextBoxOutput.InvokeRequired)
{
Action act = () =>
{
this.richTextBoxOutput.AppendText(line + Environment.NewLine);
};
this.BeginInvoke(act);
}
else
{
richTextBoxOutput.AppendText(line + Environment.NewLine);
}
}
Everything works well. But when I run a console application that needs input (for example Console.ReadLine()), my application crashes link (not responding). How can I send input to the redirected console application throughout its run?
i have a little question. Is it possible to get the logging stream (logging module) from a python script in C# using Process and ProcessStartInfo ?
As example:
ProcessStartInfo start = new ProcessStartInfo();
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
start.FileName = "runtime\\bin\\python\\python_mcp";
start.Arguments = "runtime\\decompile.py %*";
start.CreateNoWindow = true;
start.UseShellExecute = false;
bBuild = true;
sStatus = "Decompiling...";
Process proc = new Process();
proc.StartInfo = start;
this.Invoke((MethodInvoker)delegate { rtOut.Clear(); });
OutputMsg("========== Decompiling Binaries ==========");
this.Invoke((MethodInvoker)delegate { proc.Start(); });
while (!proc.StandardOutput.EndOfStream)
{
OutputMsg(proc.StandardOutput.ReadLine());
}
this.Invoke((MethodInvoker)delegate { proc.WaitForExit(); });
this.Invoke((MethodInvoker)delegate { proc.Close(); });
OutputMsg("========== Finished decompiling ==========");
bBuild = false;
sStatus = sIdleMessage;
but proc.StandardOutput.ReadLine() does not get any output.
The standart print() output from python is caught but not the logging one
I hope someone can help me.
I'm currently building a simple application, and it starts openvpn.exe. However, openvpn.exe asks for an username and password.
But, when this happens, my program does not read the string, it simply waits until the CMD is closed and then continues on with the code. So, it blocks until the window is closed.
Is there any way to circumvent this? My code is as follows:
void button_Connect_Click(object sender, EventArgs e)
{
var proc = new Process();
proc.StartInfo.FileName = #"C:\Program Files (x86)\OpenVPN\bin\openvpn.exe";
proc.StartInfo.Arguments = "--config config.ovpn --auto-proxy";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.WorkingDirectory = #"C:\Program Files (x86)\OpenVPN\bin";
// set up output redirection
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
// Input
proc.StartInfo.RedirectStandardInput = true;
// Other
proc.EnableRaisingEvents = true;
proc.StartInfo.CreateNoWindow = false;
// see below for output handler
proc.ErrorDataReceived += proc_DataReceived;
proc.OutputDataReceived += proc_DataReceived;
proc.Start();
myStreamWriter = proc.StandardInput;
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();
}
void proc_DataReceived(object sender, DataReceivedEventArgs e)
{
// output will be in string e.Data
if (e.Data != null)
{
string Data = e.Data.ToString();
if (Data.Contains("Enter Auth Username"))
{
this.myStreamWriter.WriteLine("myinput");
}
}
}
The proc_DataReceived is triggered on new line. Assuming the password is the only input that console app is asking for, you can just send it to your myStreamWriter right after starting the process. It will be buffered and consumed when necessary.