Determine if process is waiting for user input [duplicate] - c#

I am using the Process class to run an exe.
The exe is a 3rd party console application that I do not control.
I wish to know whether the process is waiting for input on the command line.
Should it make any difference, I intend to kill the application should it be waiting for input.
There are suitable events for when there is output from the program waiting to be read, but I cannot see anything similar for when the process is waiting patiently for input.
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "myapp.exe";
info.CreateNoWindow = true;
info.UseShellExecute = false;
info.RedirectStandardError = true;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
process.StartInfo = info;
process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
process.ErrorDataReceived += new DataReceivedEventHandler(process_ErrorDataReceived);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
How do I detect that my process is waiting for input?

Depending on what the 3rd party process is doing exactly you could try polling its threads' states:
foreach(ProcessThread thread in process.Threads)
if (thread.ThreadState == ThreadState.Wait
&& thread.WaitReason == ThreadWaitReason.UserRequest)
process.Kill();
Failing that... you can try to
process.StandardInput.Close();
after calling Start(), I conjecture that an exception will be raised in the child process if it's trying to read from standard input.

If the console application has some sort of prompt waiting for input, you could periodically parse out the console output text using the Process.StandardOutput property of the process and wait for said prompt. Once the proper string is detected, you know that it's waiting for input. See http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput.aspx.

Use process.StandardInput.writrLine("input");
for sending input to consol in c#

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 to stop ffmpeg process after it has finished processing in C#?

I am trying to stop the ffmpeg process once it has finished doing what I want it do, but I am not able to find a way.
Here is what I have done.
//Process for running ffmpeg
Process process = new Process();
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.FileName = ffmpegfile;
process.StartInfo.Arguments = commandtorun;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();
process.WaitForExit();
process.Close();
The problem is ffmpeg does not tell the process to stop after it has finished executing, so I cant use WaitForExit() call.
What i tried doing is
commandtorun = commandtorun+ " && exit";
to force ffmpeg to close after it finishes executing. Now this works when I try in cmd.
But when I do the same thing in C#, ffmpeg closes down as soon as the command is executed.
Is there any way to force ffmpeg or the process to close after the processing is done ?
Try
process.StartInfo.UseShellExecute = true;
This will force the process to run in shell. I don't know why it did not work using standard execution but sometimes processes behave differently in shell execute.

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.

Understanding how to control stdout using System.Diagnostics.Process

I see several questions about how to launch processes and push data into stdin, but not how to control where their output goes.
First here is my current code, run from a console mode C# application:
// Prepare the process to run
ProcessStartInfo start = new ProcessStartInfo();
// Enter in the command line arguments, everything you would enter after the executable name itself
start.Arguments = " -";
// Enter the executable to run, including the complete path
start.FileName = "doxygen.exe";
// Do you want to show a console window?
start.WindowStyle = ProcessWindowStyle.Normal;
start.CreateNoWindow = false;
start.RedirectStandardInput = true;
start.UseShellExecute = false;
// Run the external process & wait for it to finish
using (Process proc = Process.Start(start))
{
//doxygenProperties is just a dictionary
foreach (string key in doxygenProperties.Keys)
proc.StandardInput.WriteLine(key+" = "+doxygenProperties[key]);
proc.StandardInput.Close();
proc.WaitForExit();
// Retrieve the app's exit code
int exitCode = proc.ExitCode;
}
What happens when I run this is I do not see any new window (though I think I should) and all of doxygen.exe's stdout is printed to my app's console window.
What I would like to happen is one of two things:
Doxygen is launched in a visible window, and I can see its stdout in that window, not in my app's window.
Doxygen is launched in a hidden window, and it's stdout is written to a log file.
How can I achieve these?
In addition, why am I not getting a separate window for the spawned process, and why is the spawned process writing output to my window not its own?
One thing that you can do is use RedirectStandardOutput and instead of using WaitForExit you can use ReadToEnd
ProcessStartInfo start = new ProcessStartInfo();
start.RedirectStandardOutput = true;
//make other adjustments to start
Process p = new Process();
p.StartInfo = start;
p.Start();
string output = p.StandardOutput.ReadToEnd();
and then you can use string output at your leisure
If you want to get output in real-time the p.StandardOutput property has methods that allow you to get the output asynchronously. I don't know all the details to it offhand, I've only used it once before, but there's plenty of literature out there if you search for it.
Also be careful when redirecting both StandardOutput and StandardError at the same time, If they're long enough, it is possible for that to cause deadlocks.
You need to do two things:
1) Indicate that you want the standard output of the process to be directed to your app by setting the RedirectStandardOuput property to true in the process.
2) BEFORE the call to WaitForExit, start capturing the output:
string sOutput = p.StandardOutput.ReadToEnd();
If you do not start reading the output before calling wait for exit, you can encounter a deadlock.
However, it is important to know that standard output will only capture output information, not anything written to the standard error stream of the app.
In order to capture both streams of information, you can hook the process's OutputDataReceived and ErrorDataReceived events and write the event data directly into a log file or store it in a class property for use after the process has completed.

Process Exited event not firing from within webservice

I am attempting to wrap a 3rd party command line application within a web service.
If I run the following code from within a console application:
Process process= new System.Diagnostics.Process();
process.StartInfo.FileName = "some_executable.exe";
// Do not spawn a window for this process
process.StartInfo.CreateNoWindow = true;
process.StartInfo.ErrorDialog = false;
// Redirect input, output, and error streams
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.EnableRaisingEvents = true;
process.ErrorDataReceived += (sendingProcess, eventArgs) => {
// Make note of the error message
if (!String.IsNullOrEmpty(eventArgs.Data))
if (this.WarningMessageEvent != null)
this.WarningMessageEvent(this, new MessageEventArgs(eventArgs.Data));
};
process.OutputDataReceived += (sendingProcess, eventArgs) => {
// Make note of the message
if (!String.IsNullOrEmpty(eventArgs.Data))
if (this.DebugMessageEvent != null)
this.DebugMessageEvent(this, new MessageEventArgs(eventArgs.Data));
};
process.Exited += (object sender, EventArgs e) => {
// Make note of the exit event
if (this.DebugMessageEvent != null)
this.DebugMessageEvent(this, new MessageEventArgs("The command exited"));
};
process.Start();
process.StandardInput.Close();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
int exitCode = process.ExitCode;
process.Close();
process.Dispose();
if (this.DebugMessageEvent != null)
this.DebugMessageEvent(this, new MessageEventArgs("The command exited with code: " + exitCode));
All events, including the "process.Exited" event fires as expected. However, when this code is invoked from within a web service method, all events EXCEPT the "process.Exited" event fire.
The execution appears to hang at the line:
process.WaitForExit();
Would anyone be able to shed some light as to what I might be missing?
As it turns out the problem was caused by the executable that I was trying to invoke.
Unfortunately, this 3rd party executable was a port of a UNIX command that was being run through a kind of emulator. The executable was designed to output messages to the output and error streams as one would expect. However, the toolkit our vendor used to port the binaries over to Windows does not use the standard output streams.
When I stepped through the web service and manually invoked the process from the command line, I saw the emulator display an error dialog box. From the C# point of view, the process does not complete unless the [OK] button is clicked on the dialog box hence the "Exited" event never fires.
After speaking with our vendor for the executable I learned it is not fully supported in 64-bit Windows. I installed the web service on a 32-bit environment and everything was fine.
What's the process you are running in there? Since you mentioned its a console application, perhaps, it was waiting for more input? Since running this as a webservice, is the executable running under the same permissions as the ASP webservice? It could be that the web-service is not releasing the executable as that is loaded in process, or that the web-service is designated to run forever until IIS gets restarted and then the Process's Exit event may get fired.
It has come to my attention also, that there is no using clause around the Process's instantiated object i.e.
using (Process proc = new Process())
{
}
Edit: Also, please see here a link to a similar concept. The only thing after comparing the results is that the property WindowStyle is set...
ps.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

Categories