C# Process WaitForExit hangs when starting python - c#

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

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.

How do I start a new process with a new window, from a console application?

I'm developing a Console Application in C# that starts and manages other console applications.
When I use System.Diagnostics.Process.Start('anotherapp.exe");, the output from the process is printed to my current console application.
In this instance, I'm not able to redirect the output as some of the applications forcibly control their stdout.
How do I force the new process to start & use it's own window/console?
The following have provided no difference in results:
process.StartInfo.UseShellExecute = true;
process.StartInfo.CreateNoWindow = false;
process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
The output from the process is printed to its own window only. After starting that process, the managing program is ends/closed. So, the called application is only currently opened.
Try Console.Read() in calling application.
static void Main(string[] args)
{
var process = new Process();
process.StartInfo.FileName = #"D:\repos\check\check\bin\Debug\check.exe"; // just for example, you can use yours.
process.StartInfo.UseShellExecute = true;
process.StartInfo.CreateNoWindow = false;
process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
process.Start();
Console.Read();
}
I tried this code to call another application. check.exe is opened and displayed its value seperately.
We can also use Thread.Sleep(int.MaxValue)
process.WaitForExit(); can also be used after process.Start(). This will wait for new application to close.

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.

Alternative native api for Process.Start

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();

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