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.
Related
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.
I'm sorry if the title is not matching the precise description of the issue I'm facing, I accept suggestions for edits.
I'm developing a component that, when called, shall start a Process and wait for it to complete. The Process might want to redirect std output to a custom winform (a popup) for the user to have a feedback on the Process status.
In order to test the component before implementing it in the official application, I've developed a Console app that calls the module, in the same way the official application will do accepting user input from the GUI --> not the popup, the application main window.
When tested in the Console app, everything works as I expect. When testing in the official GUI application, the Process ends prematurely, with exit code 0 (all fine). I mean, it prints something in the user winform, up to a certain point, always the same point, then exits.
I can't understand why or how to identify root causes and maybe do something about it. I'm looking for help, hereafter the module source code for process execution:
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = myExePath;
processStartInfo.Arguments = myExeArguments;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardError = false;
processStartInfo.UseShellExecute = false;
processStartInfo.CreateNoWindow = true;
using (Process process = Process.Start(processStartInfo))
{
process.EnableRaisingEvents = true;
// accessory code. Issue is reproduced even without this section ---- //
Thread t = new Thread(() =>
{
// show a custom winform for the user to read
});
t.Start();
// ------------------------------------------ //
process.OutputDataReceived += (s, a) => {
// Do something with a.Data
};
process.BeginOutputReadLine();
process.WaitForExit();
}
EDIT:
let's say that the Process myExe should print something to stdout. I read this something and it goes along these lines:
line 1
line 2
I'm doing something
line 3
start doing something else <-- when component is integrated in official application, here Process Exits without exceptions
line 4
line 5 <-- When component is tested in Console app, here is where Process Exits without exceptions.
I should read up to line 5 in both testing scenario and official scenario.
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.
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;
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();