Why do I NOT get 3 lines of output from running TestApp remotely? In string 'output' I get license info plus "Start#" line, BUT not the next two lines:
public static string RunPsExec()
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.FileName = #"C:\Users\Vence\Downloads\PSTools\PsExec.exe";
p.StartInfo.Arguments = #"\\10.215.yy.yy -u xxxxxx -p ""xxxxxx"" C:\Projects\TestApp\TestApp\bin\Debug\TestApp.exe";
p.Start();
string output = p.StandardOutput.ReadToEnd();
string errormessage = p.StandardError.ReadToEnd();
p.WaitForExit();
return output;
}
TestApp:
static void Main(string[] args)
{
Console.WriteLine("Start# " + DateTime.Now.ToShortTimeString());
System.Threading.Thread.Sleep(5000);
Console.WriteLine("Middle# " + DateTime.Now.ToShortTimeString());
System.Threading.Thread.Sleep(5000);
Console.WriteLine("End# " + DateTime.Now.ToShortTimeString());
}
One solution that I see is set RedirectStandardInput to false, since it is not needed in this example.
However, if you would like to pass the input to the TestApp in a future (which requires RedirectStandardInput=true), one solution might be to use PAexec (https://www.poweradmin.com/paexec/) as an alternative to PsExec. According to these question (Can't receive asynchronous output from psexec when launching application remotely), PAExec writes directly to console buffer, instead of stout/sterr. To make it work, you would have to read the output asynchronously, like this:
public static string RunPsExec()
{
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.FileName = #"C:\<path_to>\PaExec.exe";
p.StartInfo.Arguments = #\\10.215.yy.yy -u xxxxxx -p ""xxxxxx"" ""C:\Projects\TestApp\TestApp\bin\Debug\TestApp.exe"" ";
p.OutputDataReceived += (sender, args) => Display(args.Data);
p.Start();
p.BeginOutputReadLine();
p.WaitForExit(10000);
return;
}
static void Display(string output)
{
Console.WriteLine(output);
}
Related
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!
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);
try
{
string filename = "E:\\sox-14-4-0\\mysamplevoice.wav";
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "E:\\sox-14-4-0\\sox.exe ";
p.StartInfo.Arguments = filename + " -n stat";
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
}
catch(Exception Ex)
{
Console.WriteLine(Ex.Message);
}
The output is always empty. When I run that sox command in command prompt I could get a response like:
E:\sox-14-4-0>sox mysamplevoice.wav -n stat
Samples read: 26640
Length (seconds): 3.330000
Scaled by: 2147483647.0
Maximum amplitude: 0.515625
Minimum amplitude: -0.734375
Midline amplitude: -0.109375
Mean norm: 0.058691
Mean amplitude: 0.000122
RMS amplitude: 0.101146
Maximum delta: 0.550781
Minimum delta: 0.000000
Mean delta: 0.021387
RMS delta: 0.041831
Rough frequency: 526
Volume adjustment: 1.362
When running the same command in C# I get the same result but value of "output" is empty.
Are you sure sox.exe writes to STDOUT and not to STDERR ?
you could try reading the data using the OutputDataReceived event instead.
string filename = "E:\\sox-14-4-0\\mysamplevoice.wav";
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = "E:\\sox-14-4-0\\sox.exe ";
p.StartInfo.Arguments = filename + " -n stat";
p.OutputDataReceived += process_OutputDataReceived;
p.ErrorDataReceived += process_ErrorDataReceived;
p.Start();
p.BeginErrorReadLine();
p.BeginOutputReadLine();
void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
string s = e.Data;
}
void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
string s = e.Data;
}
I just ran into this problem too. Why does SoX write to StandardError?!
In case someone else runs into this problem too, the solution to the original question could just be adding 2 lines
p.StartInfo.RedirectStandardError = true; // <-- this
...
string output = p.StandardOutput.ReadToEnd();
if(output == "") output = p.StandardError.ReadToEnd(); // <-- and this
Is there anyway to redirect standard output of a spawned process and capture it as its happening. Everything I have seen just does a ReadToEnd after the process has finished. I would like to be able to get the output as it is being printed.
Edit:
private void ConvertToMPEG()
{
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
//Setup filename and arguments
p.StartInfo.Arguments = String.Format("-y -i \"{0}\" -target ntsc-dvd -sameq -s 720x480 \"{1}\"", tempDir + "out.avi", tempDir + "out.mpg");
p.StartInfo.FileName = "ffmpeg.exe";
//Handle data received
p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
p.Start();
}
void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Debug.WriteLine(e.Data);
}
Use Process.OutputDataReceived event from the process, to recieve the data you need.
Example:
var myProc= new Process();
...
myProc.StartInfo.RedirectStandardOutput = true;
myProc.OutputDataReceived += new DataReceivedEventHandler(MyProcOutputHandler);
...
private static void MyProcOutputHandler(object sendingProcess,
DataReceivedEventArgs outLine)
{
// Collect the sort command output.
if (!String.IsNullOrEmpty(outLine.Data))
{
....
}
}
So after a little more digging I found out that ffmpeg uses stderr for output. Here is my modified code to get the output.
Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.Arguments = String.Format("-y -i \"{0}\" -target ntsc-dvd -sameq -s 720x480 \"{1}\"", tempDir + "out.avi", tempDir + "out.mpg");
p.StartInfo.FileName = "ffmpeg.exe";
p.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived);
p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
p.Start();
p.BeginErrorReadLine();
p.WaitForExit();
I want to delete multiple string lines of files output.which file is redirected.
My code is as follows.
static void Main(string[] args)
{
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd ";
p.StartInfo.UseShellExecute = false;
p.StartInfo.Arguments = "/C ipconfig";
p.StartInfo.RedirectStandardOutput = true;
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
Console.ReadLine();
}
OUTPUT : I give correct answer.but i want only ip address of m/c. Other lines are deleted.
please give the answer of question with changes of code.
Do you really need to run ipconfig? The NetworkInterface class should be able to provide you the information you are looking for without requiring you to run an external process and parse text.
static void Main(string[] args)
{
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd ";
p.StartInfo.UseShellExecute = false;
p.StartInfo.Arguments = "/C net view";
p.StartInfo.RedirectStandardOutput = true;
p.Start();
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
Console.WriteLine(output);
Console.ReadLine();
}
OUTPUT :
server name remark
//st1
//st2
//satishlap
//st6
//st10
command is completed successfully.
I give correct output.I want to only server name(//st1,//st2,//satishlap,//st6,//st10).
other infoemation is deleted. please the answer of my question with the changes of code.