Hello i'am creating a process in c# that opens a node.js, so far so good but the process seems to end and tipically when i execute the same command from my cmd it stays alive, how can i achieve such thing from c#? Here is the code of the Process
private void buttonStartLLodiAgent_Click(object sender, EventArgs e)
{
//proc.WaitForExit();
ProcessStartInfo psi = new ProcessStartInfo();
psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.RedirectStandardError = true;
psi.FileName = "node.exe";
psi.Arguments = AppDomain.CurrentDomain.BaseDirectory + "/LLodiAgent/main.js";
using (var process = Process.Start(psi))
{
//labelStatusLLodiAgent.Text = "Active";
process.BeginOutputReadLine();
process.OutputDataReceived += proc_OutputDataReceived;
//process.WaitForExit();
}
}
public void proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
outputConsole.Text = outputConsole.Text + "\r\n" + e.Data;
}
I get my Output right, but it seems like the Node service is not up, so i guess it executes but then kills it.
How to keep the server alive and the c# recieving data?
Thanks in advance, (this is my first post)
Related
Im running an exe through process in my c# program, i want the process to be completely invisible without the console of it popping up.
This is my code
Process process2 = new Process();
process2.StartInfo.FileName = "cmd.exe";
process2.StartInfo.UseShellExecute = false;
process2.StartInfo.CreateNoWindow = true;
process2.StartInfo.RedirectStandardOutput = true;
process2.StartInfo.RedirectStandardError = true;
process2.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process2 = Process.Start(path3);
even with this code the console window still opens and shows, any help will be appreciated :)
Using
UseShellExecute = false; CreateNoWindow = true;
Should hide the process although it depends on the path in which you are opening, if the process has a force show
Try the following:
private void RunCmd(string exePath, string arguments = null)
{
//create new instance
ProcessStartInfo startInfo = new ProcessStartInfo(exePath, arguments);
startInfo.Arguments = arguments; //arguments
startInfo.CreateNoWindow = true; //don't create a window
startInfo.RedirectStandardError = true; //redirect standard error
startInfo.RedirectStandardOutput = true; //redirect standard output
startInfo.RedirectStandardInput = false;
startInfo.UseShellExecute = false; //if true, uses 'ShellExecute'; if false, uses 'CreateProcess'
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.ErrorDialog = false;
//create new instance
using (Process p = new Process { StartInfo = startInfo, EnableRaisingEvents = true })
{
//subscribe to event and add event handler code
p.ErrorDataReceived += (sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
//ToDo: add desired code
Debug.WriteLine("Error: " + e.Data);
}
};
//subscribe to event and add event handler code
p.OutputDataReceived += (sender, e) =>
{
if (!String.IsNullOrEmpty(e.Data))
{
//ToDo: add desired code
Debug.WriteLine("Output: " + e.Data);
}
};
p.Start(); //start
p.BeginErrorReadLine(); //begin async reading for standard error
p.BeginOutputReadLine(); //begin async reading for standard output
//waits until the process is finished before continuing
p.WaitForExit();
}
}
See also this post.
I fixed it by renaming the window instead ty for all your help
I'm currently trying to create new NodeJS process and while it's running, put it's console output into my winform textbox.
Whenever this process is executed, it's freezing main thread as if form is waiting for this process to exit. After the process is closed thats when the console output is added to the textbox.
What I'm trying to achieve is simultaneously have this node process running in the background and have whatever it's outputing in the textbox.
Edit 1:
I Managed to run the console without freezing main thread but the output only shows when the process is closed
My current code:
private void Btn_connect_Click(object sender, EventArgs e)
{
if(backgroundWorker1.IsBusy != true)
{
backgroundWorker1.RunWorkerAsync();
}
}
private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
var worker = sender as BackgroundWorker;
nodeProcess = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "node.exe";
startInfo.Arguments = #"path" + " arg1 arg2 arg3";
startInfo.UseShellExecute = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.RedirectStandardOutput = true;
nodeProcess.StartInfo = startInfo;
nodeProcess.Start();
while (worker.CancellationPending != true)
{
Thread.Sleep(200);
AddText(nodeProcess.StandardOutput.ReadToEnd());
worker.ReportProgress(1);
}
e.Cancel = true;
}
public void AddText(string text)
{
if(txt_log.InvokeRequired)
{
txt_log.Invoke(new Action<string>(AddText), new object[] { text });
return;
}
txt_log.Text += "\n " + text;
}
Instead of a BackgroundWorker you could try using Process.BeginOutputReadLine, Process.OutputDataReceived, and Process.Exited.
void StartProcess()
{
Process nodeProcess = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "node.exe";
startInfo.Arguments = #"path" + " arg1 arg2 arg3";
startInfo.UseShellExecute = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.RedirectStandardOutput = true;
nodeProcess.StartInfo = startInfo;
nodeProcess.EnableRaisingEvents = true;
nodeProcess.Exited += nodeProcess_Exited;
nodeProcess.OutputDataReceived += nodeProcess_OutputDataReceived;
nodeProcess.Start();
nodeProcess.BeginOutputReadLine();
}
void nodeProcess_Exited(object sender, EventArgs e)
{
// Do something when the process exits, if you need to.
// You'll want to check InvokeRequired before you modify any of your form's controls.
}
void nodeProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (txt_log.InvokeRequired)
{
txt_log.Invoke(new Action<string>(AddText), new object[] { e.Data });
return;
}
txt_log.Text += "\n " + e.Data;
}
I am currently struggling with bringing existing data in batch file to C# window form
The whole objective is getting a result lively from batch file to C# rich text box but I am keep getting failure of doing it.
The procedure works like click button->run batch file secretly->C# gets data lively->display in rich text box
I was successful to run a batch file but it runs in another new CMD causing hanging problem during debugging.
I would like to know whether anyone can wrote me a code to overcome such problem. Hope for the best answer
ProcessStartInfo cmd = new ProcessStartInfo();
Process process = new Process();
cmd.FileName = #"cmd";
cmd.UseShellExecute = false;
cmd.RedirectStandardError = true;
cmd.RedirectStandardInput = true;
cmd.RedirectStandardOutput = true;
cmd.CreateNoWindow = true;
process.EnableRaisingEvents = false;
process.StartInfo = cmd;
process.Start();
process.StandardInput.Write(#"cd C:\Users\%username%\Desktop\Claymore's Dual Ethereum+Decred_Siacoin_Lbry_Pascal AMD+NVIDIA GPU Miner v11.0" + Environment.NewLine);
process.StandardInput.Write(#"EthDcrMiner64.exe -allpools 1 -epool asia1.ethereum.miningpoolhub.com:20535 -ewal AJStudio.AJStudio001 -epsw x -esm 2" + Environment.NewLine);
process.StandardInput.Close();
string result = process.StandardOutput.ReadToEnd();
StringBuilder sb = new StringBuilder();
sb.Append("[result info]" + DateTime.Now + "\r\n");
sb.Append(result);
sb.Append("\r\n");
richTextBox1.Text = sb.ToString();
process.WaitForExit();
process.Close();
To get real-time feedback from Process, use OutputDataReceived and ErrorDataReceived events. Something like this:
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.OutputDataReceived += Process_OutputDataReceived;
process.ErrorDataReceived += Process_ErrorDataReceived;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
private void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data == null) return;
log("ERROR: " + e.Data);
}
private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data == null) return;
log(e.Data);
}
I have found many examples of coding on how to execute cmd.exe and execute a command, and execute even nslookup and interact, but the problem I am having is with a particular dos program that when it starts, it does not stop "outputting". here is some code and I will put a comment and the errors I get from C#
Here is how I have it setup in a more advanced way so I can receive output from the program on events
public void StartApplication(string appNameAndPath)
{
StreamReader outputStream;
Process p = new Process();
p.StartInfo.FileName = appNameAndPath;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = false;//for now just so I can see it
p.Start();
//here is my advanced example
if(advanced == true)
{
outputStream = p.StandardOutput;
DoReadOutPut();
}
else
{//here is a simple example
while (p.StandardOutput.ReadLine() != null) //this hangs here until the application exists
{
txt += (p.StandardOutput.ReadLine());
}
}
}
void DoReadOutput()
{
outputStream.BaseStream.BeginRead( readOutputBuffer, 0, readOutputBuffer.Length, new AsyncCallback( OnReadOutputCompleted ), null );
//this does sometimes fire but only with 0 bytes, on other dos programs it would say Memory read not allowed
}
void OnReadOutputCompleted( IAsyncResult result )
{
int cbRead = outputStream.BaseStream.EndRead( result );
ProcessOutput( readOutputBuffer, cbRead );
DoReadOutput();
}
private void ProcessOutput(byte[] buffer, int cbRead)
{
string text = p.StartInfo.StandardOutputEncoding.GetString(buffer, 0, 10000); //this is where it hangs until the program exits or is not writing anymore
this.Invoke((Action)delegate
{
SetTextBoxValue(text);//im doing this because im on another thread otherwise textBox1.Text - text"
});
}
I do not want to have to use API and GetText and create an engine to ReadLastLine, can anyone help me with this? I suppose you would want an example exe, creating a C# application that while(true){Console.WriteLine("bla");} would suffice as the example exe but not the exe I am having trouble with. The exe takes over the dos window and has an "old school interface"
async/await can help here....
await Exec(yourExe,parameters);
Task Exec(string exe,string args)
{
var tcs = new TaskCompletionSource<object>();
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = exe;
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.Arguments = args;
var proc = Process.Start(psi);
proc.OutputDataReceived += (s, e) =>
{
this.Invoke((Action) (()=>richTextBox1.AppendText(e.Data + Environment.NewLine)));
};
proc.Exited += (s, e) => tcs.SetResult(null);
proc.EnableRaisingEvents = true;
proc.BeginOutputReadLine();
return tcs.Task;
}
You need to handle callback events to read streams:
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
Process proc = new Process();
proc.StartInfo = startInfo;
proc.ErrorDataReceived += new DataReceivedEventHandler(DataReceiveHandler);
proc.OutputDataReceived += new DataReceivedEventHandler(DataReceiveHandler);
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();
Code borrowed from this post
I'm using a 3rd party console application that periodically outputs data to the console line by line. When I attempted to run it through my App so that I can parse the output data, I noticed that the OutPutstream was readable only AFTER the application quits.
I tested my application with a C# console application that outputs something to the console every 5 seconds and it's working as expected. The 3rd party process I'm calling is either written in Java or C++ (not sure), but it seems that it might not adhere to the standards that .NET expects of console applications.
Is there another way to read the data output by a console application?
Edit: I'm calling the process from a WPF application. So async reads are required.
Edit 2: The console application reads data from a USB device (an accelerometer - http://www.gcdataconcepts.com/).
Below is the code I used:
public void RunProcess()
{
Process process = new Process();
process.StartInfo.FileName = "consoleApp.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
process.Start();
process.BeginOutputReadLine();
}
private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
if (!string.IsNullOrEmpty(outLine.Data))
{
Dispatcher.Invoke(new Action(() =>
{
textBlock1.Text += outLine.Data + Environment.NewLine;
}), System.Windows.Threading.DispatcherPriority.Normal);
}
}
protected virtual void StartProcess() {
// Start a new process for the cmd
process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = FileName;
process.StartInfo.Arguments = Arguments;
process.StartInfo.WorkingDirectory = WorkingDirectory;
process.Start();
// Invoke stdOut and stdErr readers - each
// has its own thread to guarantee that they aren't
// blocked by, or cause a block to, the actual
// process running (or the gui).
new MethodInvoker(ReadStdOut).BeginInvoke(null, null);
new MethodInvoker(ReadStdErr).BeginInvoke(null, null);
}
/// <summary>
/// Handles reading of stdout and firing an event for
/// every line read
/// </summary>
protected virtual void ReadStdOut() {
string str;
while ((str = process.StandardOutput.ReadLine()) != null)
{
FireAsync(StdOutReceived, this, new DataReceivedEventArgs(str));
}
}
/// <summary>
/// Handles reading of stdErr
/// </summary>
protected virtual void ReadStdErr() {
string str;
while ((str = process.StandardError.ReadLine()) != null)
{
FireAsync(StdErrReceived, this, new DataReceivedEventArgs(str));
}
}
You can also do it like this:
public void RunProcess()
{
Process process = new Process();
process.StartInfo.FileName = "consoleApp.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.Start();
for (; ; )
{
string line = process.StandardOutput.ReadLine();
if (line == null)
break;
Dispatcher.Invoke(new Action(() =>
{
textBlock1.Text += outLine.Data + Environment.NewLine;
}), System.Windows.Threading.DispatcherPriority.Normal);
}
...
}
A simpler way would be to use StandardOutput object on your process object. Example code:
Process process = new Process();
process.StartInfo.FileName = #"StackOverflowTest.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.Start();
while (!process.StandardOutput.EndOfStream)
{
Console.WriteLine("got: " + process.StandardOutput.ReadLine());
}