Get my process output in ErrorDataReceived instead of OutputDataReceived - c#

In my application I'm opening a Tshark process and start capturing. In order to update my UI, I want to get my process output but I received this output in ErrorDataReceived instead of OutputDataReceived.
public void startCapturing()
{
ProcessStartInfo tsharkStartInfo = new ProcessStartInfo();
tsharkStartInfo.FileName = _tshark;
tsharkStartInfo.RedirectStandardOutput = true;
tsharkStartInfo.RedirectStandardError = true;
tsharkStartInfo.RedirectStandardInput = true;
tsharkStartInfo.UseShellExecute = false;
tsharkStartInfo.CreateNoWindow = true;
tsharkStartInfo.Arguments = string.Format(" -i " + _interfaceNumber +
" -s " + _packetLimitSize + " -w " + _pcapPath);
_tsharkProcess.StartInfo = tsharkStartInfo;
_tsharkProcess.ErrorDataReceived += _cmdProcess_ErrorDataReceived;
_tsharkProcess.OutputDataReceived += tshark_OutputDataReceived;
_tsharkProcess.EnableRaisingEvents = true;
_tsharkProcess.Start();
_tsharkProcess.BeginOutputReadLine();
_tsharkProcess.BeginErrorReadLine();
_tsharkProcess.WaitForExit();
}
void _cmdProcess_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
int.TryParse(e.Data, out _numberOfPackets);
}
void tshark_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
string str = e.Data;
}

Related

reg delete always bringing prompt in c#

I'm using a commandline execute to run a reg delete /f. Now when I do it via commandline it works as intended, but if I run it from C# I still get a prompt.
Now I'm wondering where the erorr lies....thus why do I still get a prompt when I call the command via C# despite the /f parameter being used.
Edit: A small info here: .NET Framework is 3.5
The code that is being used is as follows:
LaunchProcessAndWait(#"cmd",
#"/c reg delete " + "\""
+ #"HKLM\Software\Policies\Microsoft\Internet Explorer\Main"+ "\""
+ #" /v DisableFirstRunCustomize /f",
"");
public static string LaunchProcessAndWaitForOutput(string commandline, string args, bool returnError, bool returnOutput, string workingDir)
{
ProcessStartInfo info = new ProcessStartInfo(commandline, args);
if (workingDir != null)
{
info.WorkingDirectory = workingDir;
}
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
info.CreateNoWindow = true;
Process p = Process.Start(info);
string outStr = "";
string errStr = "";
p.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
outStr += e.Data + "\r\n";
});
p.ErrorDataReceived += new DataReceivedEventHandler((sender, e) =>
{
errStr += e.Data + "\r\n";
});
p.BeginOutputReadLine();
p.BeginErrorReadLine();
p.WaitForExit();
p.Close();
return "" + (returnOutput ? outStr : "") + (returnError ? errStr : "");
}
}

How to read CGMiner output?

I am trying to read the CGMiner output in a C# program I am writing. I successfully read/write the standard thread input/output. But for some reason CGMiner does not write to the standard cmd window output, and I can't read it in C#. Any ideas?
This is my process start:
public void start() {
proc = new Process();
proc.StartInfo.FileName = "CMD.exe";
proc.StartInfo.RedirectStandardInput = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.OutputDataReceived += (s, e) => updateConsoleOutput(e);
proc.Start();
proc.BeginOutputReadLine();
}
This is the function I use to write to the console:
public void RunCommand(string cmd = "") {
if (cmd.Length > 0) {
ConsoleInput = cmd;
}
StreamWriter myStreamWriter = proc.StandardInput;
myStreamWriter.WriteLine(ConsoleInput);
myStreamWriter.Flush();
ConsoleInput = String.Empty;
}
These are the functions I use to read from the console:
public delegate void consoleOutputCallback(string message);
private void updateConsoleOutput(DataReceivedEventArgs outLine) {
if (!String.IsNullOrEmpty(outLine.Data)) {
this.Dispatcher.Invoke(
new consoleOutputCallback(updateConsoleText),
new object[] { outLine.Data }
);
}
}
public void updateConsoleText(string message) {
this.OutputBlock.Text += message + "\n";
}
HINT: Don't know if it helps, but CGMiner will overwrite the entire console window, and cursor always stay at top left and does not move. All command before running CGMiner is overwritten.
Forgot to add, this is console command I use:
cd C:\cgminer\
del *.bin
cgminer.exe -o stratum+tcp://global.wemineltc.com:3335 -O yongke.1:x -g 2
You need to set the --per-device-stats flag in order for GPU stats to be written into stream
And don't forget to add this to the code in question
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardError = true;
proc.ErrorDataReceived += (s, e) => updateConsoleOutput(e);
....
proc.Start();
proc.BeginErrorReadLine();
Most of miners use standart Error stream instead of standart Output stream (to write both output data and errors) for some reason..
the only thing that made it work for me was
-T
here is my working code
Task StartGPUMiner(object set)
{
MinerParams m = new MinerParams();
m = (MinerParams)set;
var tcs = new TaskCompletionSource<object>();
Process p = new Process();
ProcessStartInfo start = new System.Diagnostics.ProcessStartInfo();
start.FileName = m.ApplicationPath + "\\cgminer\\cgminer.exe";
start.Arguments = " -I " + m.GpuIntisity + " -T --scrypt -o " + m.sProtocol + m.ServerName + ":" + m.ServerPort + " -u " + m.UserName + "." + m.WorkerName + " -p " + m.ThePassword + " " + m.GpuParams;
start.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
start.RedirectStandardOutput = true;
start.UseShellExecute = false;
start.CreateNoWindow = true;
var proc = Process.Start(start);
proc.OutputDataReceived += (s, e) =>
{
try
{
this.Invoke((Action)delegate
{
txtLog.Text += (e.Data + Environment.NewLine);
});
}
catch { }
};
try
{
proc.Exited += (s, e) => tcs.SetResult(null);
proc.EnableRaisingEvents = true;
proc.BeginOutputReadLine();
}
catch { }
return tcs.Task;
}

cannot get input from redirect Standard Input

I need get an enter command for my C# process.
my C# code work for test batch file, not for the fortran console application
I read this post: C# Process Call, Interact with Standard Input and Standard Output
but it does not work for me.
Anyone can give me some tips?
my sample batch file (test.bat):
note: this batch file simulate my another application.
#echo off
cls
dir
echo "please input enter key"
pause
tree
my C# code:
private Process _process = null;
private bool _bEnterCR = false;
private void Begin_Click(object sender, RoutedEventArgs e)
{
this.tbOutput.Text = "";
_bEnterCR = false;
if (null != _process)
{
_process.Dispose();
}
string strPathName = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
// Use ProcessStartInfo class
_process = new Process();
_process.StartInfo.CreateNoWindow = true;
_process.StartInfo.UseShellExecute = false;
_process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
_process.StartInfo.FileName = strPathName + "\\test.bat";
_process.StartInfo.WorkingDirectory = strPathName + "\\Output\\";
_process.StartInfo.RedirectStandardError = true;
_process.StartInfo.RedirectStandardInput = true;
_process.StartInfo.RedirectStandardOutput = true;
//_process.EnableRaisingEvents = true;
_process.OutputDataReceived += new DataReceivedEventHandler(OnOutputDataReceived);
_process.ErrorDataReceived += new DataReceivedEventHandler(OnOutputDataReceived);
//_process.Exited += new EventHandler(OnProcessExited);
_process.Start();
_process.BeginOutputReadLine();
_process.BeginErrorReadLine();
}
private void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (String.IsNullOrEmpty(e.Data) == false)
{
if (e.Data.Contains("please input enter key") && _bEnterCR == false)
{
Debug.WriteLine("Pause Found, Entering <CR> command");
// work for batch file, not for console application
_process.StandardInput.Write(#"\r\n");
_bEnterCR = true;
}
new Thread(() =>
{
this.Dispatcher.Invoke(new Action(() =>
{
tbOutput.AppendText(e.Data + Environment.NewLine);
}));
}).Start();
}
}

How to get the output of a process?

I am open WireShark using command line and start capture the packets, when i do it using CMD windows i can see the number of the incoming packets and this number i want to show in my application form (win form), currently this is my code but my application crash with error
static void Main(string[] args)
{
try
{
string _pcapPath = #"C:\test.pcap";
Process _tsharkProcess = new Process();
_tsharkProcess.StartInfo.FileName = #"C:\Program Files\Wireshark\tshark.exe";
_tsharkProcess.StartInfo.Arguments = string.Format(" -i " + 2 + " -c " + int.MaxValue + " -w " + _pcapPath);
_tsharkProcess.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
_tsharkProcess.StartInfo.RedirectStandardOutput = true;
_tsharkProcess.StartInfo.UseShellExecute = false;
//_tsharkProcess.StartInfo.CreateNoWindow = true;
//_tsharkProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
_tsharkProcess.Start();
StreamReader myStreamReader = _tsharkProcess.StandardOutput;
string myString = myStreamReader.ReadLine(); //read the standard output of the spawned process.
Console.WriteLine(myString);
_tsharkProcess.WaitForExit();
}
catch (Exception)
{
}
}
private static void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
string srt = e.Data; //arg.Data contains the output data from the process...
}
You can try with this code
Nota : Set these lines before start
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.Start();
Code:
Process process = new Process();
process.StartInfo.FileName = #"C:\Program Files\Wireshark\tshark.exe";
process.StartInfo.Arguments = string.Format(" -i " + _interfaceNumber + " -c " + int.MaxValue + " -w " + _pcapPath);
process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.Start();
StreamReader myStreamReader = process.StandardOutput;
// Read the standard output of the spawned process.
string myString = myStreamReader.ReadLine();
Console.WriteLine(myString);
process.WaitForExit();
process.Close();
}

I am trying to read the output of a process in c# but I get this message "Cannot mix synchronous and asynchronous operation on process stream."

I am writing a backup program using xcopy and because there are a lot of large files it takes a while so I want to show the progress. When I try to use StreamReader to get the standard output, it has this error message when I debug. "Cannot mix synchronous and asynchronous operation on process stream."
public void backup_worker_DoWork(object sender, DoWorkEventArgs e)
{
int loop = 1;
backup_worker.WorkerReportsProgress = true;
Process xcopy = new Process();
ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.CreateNoWindow = true;
startinfo.UseShellExecute = false;
startinfo.RedirectStandardError = true;
startinfo.RedirectStandardOutput = true;
startinfo.FileName = Environment.CurrentDirectory + "\\xcopy.exe";
startinfo.Arguments = '"' + source + '"' + " " + '"' + target + '"' + " " + "/s /e /y";
xcopy.StartInfo.RedirectStandardOutput = true;
xcopy.StartInfo = startinfo;
xcopy.Start();
xcopy.BeginErrorReadLine();
xcopy.BeginOutputReadLine();
StreamReader sr = xcopy.StandardOutput;
while (loop > 0)
{
progress = sr.ReadLine();
output_list.Items.Add(progress);
}
xcopy.OutputDataReceived += new DataReceivedEventHandler(backup_worker_OutputDataRecieved);
xcopy.ErrorDataReceived += new DataReceivedEventHandler(backup_worker_ErrorDataReceived);
xcopy.WaitForExit();
backup_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backup_worker_RunWorkerCompleted);
}
void backup_worker_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
}
void backup_worker_OutputDataRecieved(object sender, DataReceivedEventArgs e)
{
}
void backup_worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Completed");
}
Please help.
Thanks in advance
The problem is that you're using both synchronous and asynchronous output:
// Using async version here...
xcopy.BeginOutputReadLine();
StreamReader sr = xcopy.StandardOutput;
while (loop > 0)
{
// Trying to use synchronous reading here
progress = sr.ReadLine();
You need to design your algorithm to use one option or the other, but not both.
The below note from MSDN should make it very clear, what the problem is
You cannot mix asynchronous and synchronous read operations on a redirected stream. Once the redirected stream of a Process is opened in either asynchronous or synchronous mode, all further read operations on that stream must be in the same mode. For example, do not follow BeginErrorReadLine with a call to ReadLine on the StandardError stream, or vice versa. However, you can read two different streams in different modes. For example, you can call BeginErrorReadLine and then call ReadLine for the StandardOutput stream.
Your code should be more on the lines as below
public void backup_worker_DoWork(object sender, DoWorkEventArgs e) {
int loop = 1;
// This should ideally not be in the DoWork, but where you setup or create the worker
backup_worker.WorkerReportsProgress = true;
backup_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backup_worker_RunWorkerCompleted);
backup_worker.WorkerSupportsCancellation = true;
// setup your scopy process
ProcessStartInfo startinfo = new ProcessStartInfo();
startinfo.CreateNoWindow = true;
startinfo.UseShellExecute = false;
startinfo.RedirectStandardError = true;
startinfo.RedirectStandardOutput = true;
startinfo.FileName = Environment.CurrentDirectory + "\\xcopy.exe";
startinfo.Arguments = "/s /e /y " + '"' + source + '"' + " " + '"' + target + '"' + " ";
Process xcopy = new Process();
xcopy.StartInfo = startinfo;
xcopy.ErrorDataReceived += new DataReceivedEventHandler(backup_worker_ErrorDataReceived);
// start the xcopy and read the output
xcopy.Start();
xcopy.BeginErrorReadLine();
string copiedFileName;
while ((copiedFileName = xcopy.StandardOutput.ReadLine()) != null) {
output_list.Items.Add(copiedFileName);
}
// we should be done when here, but doesen't hurt to wait
xcopy.WaitForExit();
}
void backup_worker_ErrorDataReceived(object sender, DataReceivedEventArgs e) {
MessageBox.Show("We have a problem. Figure what needs to be done here!");
}
void backup_worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled == true) {
MessageBox.Show("Canceled!");
} else if (e.Error != null) {
MessageBox.Show("Error: " + e.Error.Message);
} else {
MessageBox.Show("Completed!");
}
}
If you want to do the synchronous way,
instead of
xcopy.BeginOutputReadLine()
use
string s = xcopy.StandardOutput.ReadToEnd()
be warned, that if you do that for both the output and the error, and one of them is too long, you can hit a deadlock.

Categories