Console application fire a process then close itself - c#

I'm writing a small updater for my app.
My flow would be like this:
app.exe -> call process(updater.exe) -> app.close()
Then, updater check if app is closed, then overwrites app.exe and other satellite assemblies.
So I need to do something like this: launch my C# exe app, fire a process for updater.exe, then close app, but without closing child process.
There's a way to build this kind of fire-and-forget process in .NET?
Thank you,
Nando

Look at the Process object. You would just call Process.Start like so:
System.Diagnostics.Process.Start("updater.exe");

Yes, I'm doing so, but seems that Process don't start...
I made a small helper class, called Updater:
Updater.CheckUpdates()
--> starts a Process who call "updater.exe -check", and that works (when process finished, control return to my main app). I evaluate return code of process, and the I set Updater.UpdatesAvalilable bool flag, if necessary.
Updater.ApplyUpdates()
--> starts a Process who call "updater.exe -update", that do the update work.
So, my code is like this:
Updater.CheckUpdates();
if (Updater.UpdatesAvailable)
{
Updater.ApplyUpdates();
System.Environment.Exit(0);
}
Process in Updater.ApplyUpdates() never run.
I know, is not elegant code, but I don't know how to achieve my goal. :-)
Thank you!
Nando

Good morning guys.
I found a way to make it work, it seems.
In my helper class I wired events for getting stdIO and stdError, just to log something; removing those, I get my work done: process start and main exit! :-)
Just to make all know about it: my process declaration is now like this:
Process process = new Process();
process.EnableRaisingEvents = true;
process.StartInfo = new ProcessStartInfo();
process.StartInfo.Arguments = "-update";
process.StartInfo.CreateNoWindow = true;
process.StartInfo.ErrorDialog = false;
process.StartInfo.FileName = "updater.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.WorkingDirectory = Directory.GetCurrentDirectory();
process.Start();
Thank you all!
Nando

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.

Closing an application gently and waiting for it exit

Somewhere in the application I create a instance of proc which is of Process type, something like this:
proc = new Process();
proc.EnableRaisingEvents = true;
proc.StartInfo.FileName = Settings.Instance.OBSExeFile;
proc.Exited += (a, b) => doSomething();
proc.Start();
proc.WaitForInputIdle();
on Form.Closing Event, I want to close it, gently, if it's still open.
I find no other way to do this with native stuff within the .NET (neither Close() nor Kill() nor CloseMainWindow() seemed to fit my needs) so I eneded up doing sending WM_CLOSE to the application and calling Process.WaitForExit(), like this:
if (proc != null && !proc.HasExited) {
if(SendMessage(proc.MainWindowHandle, WM_CLOSE, 0, IntPtr.Zero) == 0)
proc.WaitForExit();
}
My question is: Am I missing something in the sense of mixing this being dangerous in any way? Can WaitForExit()hang for ever, for example?
Based on the information you provided I think good approach will be create a Windows service instead of .exe. Then you will have full control of process.
Inside windows service you can create a code which "gently" close current service when stop command will be send to it.
send a message to it, and have it close itself (in any way that you see fit). I have a set of programs that do this, I use a udp broadcast to 127.0.0.1 for this.

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.

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

Getting a Process to terminate

I have a process object setup like the following:
Process p = new Process();
p.StartInfo.FileName = command;
p.StartInfo.UseShellExecute = true;
p.StartInfo.Arguments = String.Format(
commandArguments,
destinationLocation,
sourceLocation,
sourceDirName,
(string.IsNullOrEmpty(revisionNotes.Text)) ? "" : revisionNotes.Text);
(where undefined values are supplied externally to this code and are valid). The process in question launches and properly executes with p.Start(); but i need to catch it on termination. The console window flashes up briefly and goes away which would seem to indicate that the process is done, but none of the relevant events are fired (OutputDataRecieved, Exited, etc) and it's like the process never ends. (I'm trying to execute a lua script with some parameters if that's relevant). Can someone help me get this process to stop correctly?
WaitForExit
Have you set the EnableRaisingEvents property of the process to True? You won't catch the Exited event without it.

Categories