Alternative native api for Process.Start - c#

Ok this is not duplicate of "Alternative to Process.Start()" because my question is something different here.
I need to run a process and wait till execution of process and get the output of console.
There is way to set RedirectStandardOutput and RedirectStandardError to true, however this does not function well on some machines, (where .NET SDK is not installed), only .NET runtime is installed, now it works on some machines and doesnt work on some machines so we dont know where is the problem.
I have following code,
ProcessStartInfo info = new ProcessStartInfo("myapp.exe", cmd);
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
Process p = Process.Start(info);
p.WaitForExit();
Trace.WriteLine(p.StandardOutput.ReadToEnd());
Trace.WriteLine(p.StandardError.ReadToEnd());
On some machines, this will hang forever on p.WaitForExit(), and one some machine it works correctly, the behaviour is so random and there is no clue.
Now if I can get a real good workaround for this using pinvoke, I will be very happy.
myapp.exe is nothing but writing 10 hello world statements on screen.

Could it be that your child process really hangs for ever, eg. waiting on input or displaying an error dialog that is not visible?
The native API is CreateProcess, and it's corresponding pInvoke.

Using a separate work around by calling native code is not going to correct the problem. The Process API is just a thin wrapper around the native Process functions - using them directly is just going to make your code more confusing and cause other problems.
It sounds like the problem, in this case, is your "myapp.exe". For some reason, that application is not terminating on those machines. If you discover what is causing that, you will likely be able to make this work correctly using Process.Start.

Ok I got this answer from somewhere...
using System.Diagnostics;
using System.Threading;
ProcessStartInfo info = new ProcessStartInfo("myapp.exe", cmd);
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.RedirectStandardError = true;
info.RedirectStandardOutput = true;
Process p = new Process();
p.StartInfo = info;
p.BeginOutputReadLine();
p.BeginErrorReadLine();
AutoResetEvent wait = new AutoResetEvent(false);
p.Exited += (s,e)=>{
wait.Set();
}
p.Start();
wait.WaitOne();

Related

Can you make it so a C# program executes a CMD command on the same instance? [duplicate]

I figure out how to launch a process. But my problem now is the console window (in this case 7z) pops up frontmost blocking my vision and removing my focus interrupting my sentence or w/e i am doing every few seconds. Its extremely annoying, how do i prevent that from happening. I thought CreateNoWindow solves that but it didnt.
NOTE: sometimes the console needs user input (replace file or not). So hiding it completely may be a problems a well.
This is my current code.
void doSomething(...)
{
myProcess.StartInfo.FileName = ...;
myProcess.StartInfo.Arguments = ...;
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
myProcess.WaitForExit();
}
If I recall correctly, this worked for me
Process process = new Process();
// Stop the process from opening a new window
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
// Setup executable and parameters
process.StartInfo.FileName = #"c:\test.exe"
process.StartInfo.Arguments = "--test";
// Go
process.Start();
I've been using this from within a C# console application to launch another process, and it stops the application from launching it in a separate window, instead keeping everything in the same window.
#galets
In your suggestion, the window is still created, only it begins minimized. This would work better for actually doing what acidzombie24 wanted:
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
Try this:
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
I'll have to double check, but I believe you also need to set UseShellExecute = false. This also lets you capture the standard output/error streams.

Strange standard output behavior when blocking thread

I have a C# application that creates a thread which talks to Node.js (node.exe) over standard input.
The code to create this is pretty standard:
ProcessStartInfo NodeStart = new ProcessStartInfo();
NodeStart.FileName = FileName; // node.exe
NodeStart.Arguments = Arguments;
NodeStart.CreateNoWindow = true;
NodeStart.RedirectStandardError = true;
NodeStart.RedirectStandardInput = true;
NodeStart.RedirectStandardOutput = true;
NodeStart.UseShellExecute = false;
process = new Process();
process.OutputDataReceived += ReceivedOutput;
process.StartInfo = NodeStart;
process.Start();
process.BeginOutputReadLine();
The code works completely OK as long as I do not block the thread that is running it by using Thread.WaitOne(). As soon as I call Thread.WaitOne() something goes wrong with the input/output of the process. Next time I unblock the thread and write to standard input, I get nothing back. I inspected the process object in the debugger prior to when the standard input gets written and nothing appears to be wrong (node.exe is running and accepts the standard input).
It may simply be the case that standard input/output breaks when the thread blocks, but is this true? I couldn't find the answer anywhere.

C# Process WaitForExit hangs when starting python

I use a Process class to start Python like below (in a thread):
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "python.exe";
info.Arguments = "test.py";
Process p = new Process();
p.StartInfo = info;
p.RedirectStandardOutput = true;
p.RedirectStandardError = true;
...
p.Start();
p.WaitForExit();
when Python ends with errors (the python process is no longer showing in Windows Task Manager), WaitForExit still hangs. However, if I use IronPython instead, it works fine. Can anyone tell me why?
Resolved. Redirects and ErrorDataReceived/OutputDataReceived event implements causes this problem, use Redirects and StreamReader instead.
Try changing python.exe to pythonw.exe

Console information to window

I already know how to catch standard output of a console window, BUT my problem is the case when I get the process with GetProcesses/orByName and do not Start() it myself. Here is the code:
public ProcessCaller(ISynchronizeInvoke isi, Process MárFutóAlkalmazás)
: this(isi)
{
//alapbeállítások
FileName = MárFutóAlkalmazás.StartInfo.FileName;
Arguments = MárFutóAlkalmazás.StartInfo.Arguments;
WorkingDirectory = MárFutóAlkalmazás.StartInfo.WorkingDirectory;
//egyedi beállítások
process = MárFutóAlkalmazás;
process.EnableRaisingEvents = true;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
new MethodInvoker(ReadStdOut).BeginInvoke(null, null);
new MethodInvoker(ReadStdErr).BeginInvoke(null, null);
//események
StdErrReceived += new DataReceivedHandler(Loggolás);
StdOutReceived += new DataReceivedHandler(Loggolás);
//kilépés jelzése
process.Exited += new EventHandler(OnKilépés);
}
So this method gets and already running application as MárFutóAlkalmazás parameter. Sets some internal properties, then hooks to Output. However when it comes to
StdOutReceived += new DataReceivedHandler(Loggolás);
and the program runs the Loggolás method to take the console data, it says that the StandardOut is not set, or the process is not started.
Well:
StandardOut is set
Process is running, since I get it by GetProcesses
In this routine I do NOT use process.Start() - since it is started already
Looking for help. Thank yas:
Péter
Ok, so after asking around and checking on net, I learned that you can not hook on an output not started by you. So if your executor application crashes, you will have to restart console application to be able to capture output. You need the .Start().
Actually I see only one salvation for this problem: starting with the ">filename.txt" or such output redirecting parameter. This will stuff everything into a file, so even if executor application crashes you can "reconnect" if you "read only". Did not tested this yet, but I see no other way.

Gracefuly stop .net initiated Java Process

Having the next .net code, I want to stop it correctly so that the jvm executes it's ShutdownHooks.
System.Diagnostics.Process p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.WorkingDirectory = #"C:\test\";
p.StartInfo.FileName = #"C:\Program Files\Java\jre6u16\bin\java.exe";
p.StartInfo.Arguments = "-jar TheExecutable.jar";
Trying to stop the process with p.Kill() will force the jvm to stop without sending the equivalent SIGTERM found in the unix kill comand. Or maeby I am doing something wrong because the java process does not get it's shutdown hooks executed.
Thanks !
If you have control over the Java code, you could detect a fairly normal situation like End-Of-File in stdin, or a so-called poison pill in stdin, and use that to decide (in Java) that now is the time to exit.
Then to kill the java process, do whatever is needed to its stdin.
Another option is to write a signal handler, - see sun.misc.SignalHandler, and register this with sum.misc.Signal
Other options seem rather hideous - like polling the parent process or looking at a file.

Categories