Related
In the top of Form1 i did:
private Process zipFileDirectoryProcess;
In the constructor i did:
zipFileDirectoryProcess = new Process();
zipFileDirectoryProcess.StartInfo.FileName = "explorer.exe";
zipFileDirectoryProcess.StartInfo.CreateNoWindow = true;
zipFileDirectoryProcess.EnableRaisingEvents = true;
zipFileDirectoryProcess.Exited += new EventHandler(zipFileDirectoryProcess_Exited);
Then i have a method i call it from a button click event:
private void Compress()
{
zipFileDirectoryProcess.StartInfo.Arguments = zipFileDirectoryProcess.StartInfo.Arguments = "/select," + Path.GetFullPath(t);
zipFileDirectoryProcess.Start();
zipFileDirectoryProcess.WaitForExit();
this.TopMost = true;
}
And then in the bottom the Exited event:
private void zipFileDirectoryProcess_Exited(object sender, EventArgs e)
{
this.BeginInvoke(new MethodInvoker(delegate()
{
this.TopMost = false;
}));
}
What i wanted to do is only when i close the process window after started it in the method only if closed the window/process then do the Exited event.
The problem is that once the process started after 2-3 seconds its jumping automatic to the Exited event.
How can i fix it ? Tried examples cant figure out.
Tried to add this line:
zipFileDirectoryProcess.WaitForExit();
But no effect.
zipFileDirectoryProcess.StartInfo.FileName = "explorer.exe";
Trying to start Windows Explorer again when it is already running, and it is always running, will have a disappointing outcome. It is a "heavy" process and it intentionally tries the minimize the number of running copies. Otherwise known as a "single-instance app". There are lots like that, the Microsoft Office programs are single instance apps for example.
So what really happens is that explorer.exe actually starts up, but sees that another instance is already running. And uses process interop to ask that first instance to do the job that you asked it to do. Since you didn't ask it to do anything, you just get another window, displayed by the first instance. The one that you started immediately quits, it doesn't have anything else to do.
So, yes, you'll see that the Exited event fires without you doing anything. Accurately telling you that the explorer.exe process you started did in fact quit. Easy to see in the Taskmgr.exe Processes tab btw. Waiting for that window to be closed is never going to work, it is displayed by the original instance of explorer.exe.
This will just not work the way you hope it will work. What you are actually trying to do is not quite obvious but can be guessed at. Creating a ZIP archive is not difficult, there are excellent libraries available for C# to get the job done, no point in asking another program to do it for you. DotNetZip and SharpZipLib are very popular. It got finally added to .NET as well in version 4.5, Microsoft finally getting over the lost Stacker lawsuit, about time. If you really, really want another program to do it for you then use a console mode zipper like 7-zip.
To show output folder in windows explorer to the user, it's simply enough to do this:
Process.Start("explorer.exe", OutputDir);
Developing a C# .NET 2.0 WinForm Application. Need the application to close and restart itself.
Application.Restart();
The above method has proven to be unreliable.
What is a better way to restart the application?
A much simpler approach that worked for me is:
Application.Restart();
Environment.Exit(0);
This preserves the command-line arguments and works despite event handlers that would normally prevent the application from closing.
The Restart() call tries to exit, starts a new instance anyway and returns. The Exit() call then terminates the process without giving any event handlers a chance to run. There is a very brief period in which both processes are running, which is not a problem in my case, but maybe in other cases.
The exit code 0 in Environment.Exit(0); specifies a clean shutdown. You can also exit with 1 to specify an error occurred.
If you are in main app form try to use
System.Diagnostics.Process.Start( Application.ExecutablePath); // to start new instance of application
this.Close(); //to turn off current app
Unfortunately you can't use Process.Start() to start an instance of the currently running process. According to the Process.Start() docs:
"If the process is already running, no additional process resource is started..."
This technique will work fine under the VS debugger (because VS does some kind of magic that causes Process.Start to think the process is not already running), but will fail when not run under the debugger. (Note that this may be OS-specific - I seem to remember that in some of my testing, it worked on either XP or Vista, but I may just be remembering running it under the debugger.)
This technique is exactly the one used by the last programmer on the project on which I'm currently working, and I've been trying to find a workaround for this for quite some time. So far, I've only found one solution, and it just feels dirty and kludgy to me: start a 2nd application, that waits in the background for the first application to terminate, then re-launches the 1st application. I'm sure it would work, but, yuck.
Edit: Using a 2nd application works. All I did in the second app was:
static void RestartApp(int pid, string applicationName )
{
// Wait for the process to terminate
Process process = null;
try
{
process = Process.GetProcessById(pid);
process.WaitForExit(1000);
}
catch (ArgumentException ex)
{
// ArgumentException to indicate that the
// process doesn't exist? LAME!!
}
Process.Start(applicationName, "");
}
(This is a very simplified example. The real code has lots of sanity checking, error handling, etc)
I might be late to the party but here is my simple solution and it works like a charm with every application I have:
try
{
//run the program again and close this one
Process.Start(Application.StartupPath + "\\blabla.exe");
//or you can use Application.ExecutablePath
//close this one
Process.GetCurrentProcess().Kill();
}
catch
{ }
I had the same exact problem and I too had a requirement to prevent duplicate instances - I propose an alternative solution to the one HiredMind is proposing (which will work fine).
What I am doing is starting the new process with the processId of the old process (the one that triggers the restart) as a cmd line argument:
// Shut down the current app instance.
Application.Exit();
// Restart the app passing "/restart [processId]" as cmd line args
Process.Start(Application.ExecutablePath, "/restart" + Process.GetCurrentProcess().Id);
Then when the new app starts I first parse the cm line args and check if the restart flag is there with a processId, then wait for that process to Exit:
if (_isRestart)
{
try
{
// get old process and wait UP TO 5 secs then give up!
Process oldProcess = Process.GetProcessById(_restartProcessId);
oldProcess.WaitForExit(5000);
}
catch (Exception ex)
{
// the process did not exist - probably already closed!
//TODO: --> LOG
}
}
I am obviously not showing all the safety checks that I have in place etc.
Even if not ideal - I find this a valid alternative so that you don't have to have in place a separate app just to handle restart.
Start/Exit Method
// Get the parameters/arguments passed to program if any
string arguments = string.Empty;
string[] args = Environment.GetCommandLineArgs();
for (int i = 1; i < args.Length; i++) // args[0] is always exe path/filename
arguments += args[i] + " ";
// Restart current application, with same arguments/parameters
Application.Exit();
System.Diagnostics.Process.Start(Application.ExecutablePath, arguments);
This seems to work better than Application.Restart();
Not sure how this handles if your program protects against multiple instance. My guess is you would be better off launching a second .exe which pauses and then starts your main application for you.
It's simple, you just need to call the Application.Restart() method, this will invoke your application to be restarted. You must also exit from the local environment with an error code:
Application.Restart();
Environment.Exit(int errorcode);
You can create an enumeration of error codes so that you application will exit efficeintly.
Another method is to just exit from the application and start the process using the executable path:
Application.Exit();
System.Diagnostics.Process.Start(Application.ExecutablePath);
Try this code:
bool appNotRestarted = true;
This code must also be in the function:
if (appNotRestarted == true) {
appNotRestarted = false;
Application.Restart();
Application.ExitThread();
}
I figured an another solution out, perhaps anyone can use it, too.
string batchContent = "/c \"#ECHO OFF & timeout /t 6 > nul & start \"\" \"$[APPPATH]$\" & exit\"";
batchContent = batchContent.Replace("$[APPPATH]$", Application.ExecutablePath);
Process.Start("cmd", batchContent);
Application.Exit();
Code is simplified so take care of Exceptions and stuff ;)
I fear that restarting the entire application using Process is approaching your problem in the wrong way.
An easier way is to modify the Program.cs file to restart:
static bool restart = true; // A variable that is accessible from program
static int restartCount = 0; // Count the number of restarts
static int maxRestarts = 3; // Maximum restarts before quitting the program
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
while (restart && restartCount < maxRestarts)
{
restart = false; // if you like.. the program can set it to true again
restartCount++; // mark another restart,
// if you want to limit the number of restarts
// this is useful if your program is crashing on
// startup and cannot close normally as it will avoid
// a potential infinite loop
try {
Application.Run(new YourMainForm());
}
catch { // Application has crashed
restart = true;
}
}
}
You are forgetting the command-line options/parameters that were passed in to your currently running instance. If you don't pass those in, you are not doing a real restart. Set the Process.StartInfo with a clone of your process' parameters, then do a start.
For example, if your process was started as myexe -f -nosplash myfile.txt, your method would only execute myexe without all those flags and parameters.
I wanted the new application start up after the old one shuts down.
Using process.WaitForExit() to wait for your own process to shutdown makes no sense. It will always time out.
So, my approach is to use Application.Exit() then wait, but allow events to be processed, for a period of time. Then start a new application with the same arguments as the old.
static void restartApp() {
string commandLineArgs = getCommandLineArgs();
string exePath = Application.ExecutablePath;
try {
Application.Exit();
wait_allowingEvents( 1000 );
} catch( ArgumentException ex ) {
throw;
}
Process.Start( exePath, commandLineArgs );
}
static string getCommandLineArgs() {
Queue<string> args = new Queue<string>( Environment.GetCommandLineArgs() );
args.Dequeue(); // args[0] is always exe path/filename
return string.Join( " ", args.ToArray() );
}
static void wait_allowingEvents( int durationMS ) {
DateTime start = DateTime.Now;
do {
Application.DoEvents();
} while( start.Subtract( DateTime.Now ).TotalMilliseconds > durationMS );
}
You could also use Restarter.
Restarter is an application that automatically monitor and restarts crashed or hung programs and applications. It was originally developed to monitor and restart game servers, but it will do the job for any console or form based program or application
public static void appReloader()
{
//Start a new instance of the current program
Process.Start(Application.ExecutablePath);
//close the current application process
Process.GetCurrentProcess().Kill();
}
Application.ExecutablePath returns your aplication .exe file path
Please follow the order of calls. You might want to place it in a try-catch clause.
The problem of using Application.Restart() is, that it starts a new process but the "old" one is still remaining. Therefor I decided to Kill the old process by using the following code snippet:
if(Condition){
Application.Restart();
Process.GetCurrentProcess().Kill();
}
And it works proper good. In my case MATLAB and a C# Application are sharing the same SQLite database. If MATLAB is using the database, the Form-App should restart (+Countdown) again, until MATLAB reset its busy bit in the database. (Just for side information)
How about create a bat file, run the batch file before closing, and then close the current instance.
The batch file does this:
wait in a loop to check whether the process has exited.
start the process.
Here's my 2 cents:
The sequence Start New Instance->Close Current Instance should work even for the applications that don't allow running multiple copies simultaneously as in this case the new instance may be passed a command-line argument which will indicate that there is a restart in progress so checking for other instances running will not be necessary. Waiting for the first instance to actually finish my be implemented too if it's absolutely imperative that no two intstances are running in parallel.
Application.Restart();
Environment.Exit(0);
I had a similar problem, but mine was related to unmanageable memory leak that I couldn't find on an app that has to run 24/7. With the customer I agreed that safe time to restart the app was 03:00AM if the memory consumption was over the defined value.
I tried Application.Restart, but since it seems to use some mechanism that starts new instance while it is already running, I went for another scheme. I used the trick that file system handles persist until process that created them dies. So, from The Application, i dropped the file to the disk, and didn't Dispose() the handle. I used the file to send 'myself' executable and starting directory also (to add flexibility).
Code:
_restartInProgress = true;
string dropFilename = Path.Combine(Application.StartupPath, "restart.dat");
StreamWriter sw = new StreamWriter(new FileStream(dropFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite));
sw.WriteLine(Application.ExecutablePath);
sw.WriteLine(Application.StartupPath);
sw.Flush();
Process.Start(new ProcessStartInfo
{
FileName = Path.Combine(Application.StartupPath, "VideoPhill.Restarter.exe"),
WorkingDirectory = Application.StartupPath,
Arguments = string.Format("\"{0}\"", dropFilename)
});
Close();
Close() at the end would initiate app shutdown, and file handle I used for StreamWriter here would be held open until process really dies. Then...
Restarter.exe comes into action. It TRIES to read the file in exclusive mode, preventing it to gain access until main app wasn't dead, then starts main app, deletes the file and exists. I guess that it can't be simpler:
static void Main(string[] args)
{
string filename = args[0];
DateTime start = DateTime.Now;
bool done = false;
while ((DateTime.Now - start).TotalSeconds < 30 && !done)
{
try
{
StreamReader sr = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));
string[] runData = new string[2];
runData[0] = sr.ReadLine();
runData[1] = sr.ReadLine();
Thread.Sleep(1000);
Process.Start(new ProcessStartInfo { FileName = runData[0], WorkingDirectory = runData[1] });
sr.Dispose();
File.Delete(filename);
done = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Thread.Sleep(1000);
}
}
I use the following and it does exactly what you are looking for:
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
UpdateCheckInfo info = null;
info = ad.CheckForDetailedUpdate();
if (info.IsUpdateRequired)
{
ad.UpdateAsync(); // I like the update dialog
MessageBox.Show("Application was upgraded and will now restart.");
Environment.Exit(0);
}
for using As logout you need to terminate all app from Ram Cache
so close The Application first and then Rerun it
//on clicking Logout Button
foreach(Form frm in Application.OpenForms.Cast<Form>().ToList())
{
frm.Close();
}
System.Diagnostics.Process.Start(Application.ExecutablePath);
You could enclose your code inside a function and when restart is needed you can just call the function.
Take for instance an application that:
While application is not registered; (upon start) the application should prompt the user to register the application and create a login account.
Once registration is submitted and login credentials are created; the application should restart, check for registration and prompt the user to login with the inserted credentials (so the user can access to all the application features).
Problem:
By building and launching the application from Visual Studio; any of the 4 alternatives bellow will fail to accomplish the tasks required.
/*
* Note(s):
* Take into consideration that the lines bellow don't represent a code block.
* They are just a representation of possibilities,
* that can be used to restart the application.
*/
Application.Restart();
Application.Exit();
Environment.Exit(int errorCode);
Process.GetCurrentProcess().Kill();
What happens is: After creating the Registration, Login and calling Application.Restart(); the application will (strangely) reopen the Registration Form and skip data in a Database (even though the resource is set to "Copy if Newer").
Solution:
Batch Building the application was (for me) a proof that any of the lines above were actually working as expected.
Just not when building and running the application with Visual Studio.
In first place I'd try batch building the application; run it outside Visual Studio and check if Application.Restart() actually works as expected.
Also Check further Info regarding this thread subject:
How do I restart my C# WinForm Application?
I've found a new way that's pretty convenient and has quite a few upsides.
There's never more than one instance running.
Command line args are persisted.
No exit events are raised from the application.
No process handles are broken.
I had a third party application managing my application with Process.Start and using Exit event to reload the application. Many of these solutions would break this implementation which is how I ended up on the following solution.
public static CancellationTokenSource _restartTokenSource;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
while (_restartTokenSource == null || _restartTokenSource.IsCancellationRequested)
{
_restartTokenSource = new System.Threading.CancellationTokenSource();
_restartTokenSource.Token.Register(() =>
{
foreach (Form form in Application.OpenForms)
form.Close();
});
Application.Run(new FlashMain(args));
}
}
Since Application.Run blocks until all forms in the application are closed I put this portion of the initialization into a loop that only executes when a CancellationTokenSource is null (the first run) or IsCancellationRequested is true (restart requested).
I register an event on the CancellationTokenSource that closes all forms in the application when .Cancel() is called, therefore unblocking Application.Run and restarting the loop.
Call Program._restartTokenSource.Cancel(); anywhere in the application to restart it.
P.S. This also works great for injecting into a BlazorWebView to restart the application from .NET Core.
updated
I have a problem related to Process.Start();
My program launches files as processes, like so:
Process processMonitor = new Process();
processMonitor.StartInfo.FileName = filePath; // Example: #"C:\test.txt"
processMonitor.StartInfo.CreateNoWindow = true;
processMonitor.Exited += new EventHandler(Process_Exited);
processMonitor.EnableRaisingEvents = true;
processMonitor.Start();
// Handle Exited event and display process information.
private void Process_Exited(object sender, EventArgs e)
{
// This code is called on every exit, except images: (Windows Photo Viewer, *jpg, *png, *bmp etc.)
}
This successfully launches a process, notepad.exe with the correct file.
Catching the Exited event also works so basically i have everything in place to monitor the close event for the process.
Now for the problem...
When doing exactly the same, but now for an image:
processMonitor.StartInfo.FileName = filePath; // Example: #"C:\test.jpg"
This is not successfull.. The process launches perfectly, But i can not detect if the process is ever closed. A little research shows me that a process called:
DLLHOST.EXE (COM Surrogate)
Is launched and i cannot detect the Exited event for this process.
Can anybody help me, or at least point me in the right direction?
If all other doesn't work, you can look into WMI: http://msdn.microsoft.com/en-us/library/aa394582(v=vs.85).aspx - this will require you to do some wrapping work (or use a wrapper, like the one here: http://www.codeproject.com/Articles/21971/WMI-Interface-for-NET)
Another option you can use as last resort and as a workaround only is polling for the process state, but this is really not recommended for most project, and it certainly doesn't sound like something you want to do in your project.
I think it has to do with the nature of an image. Opening a .txt file launches notepad whereas opening a .jpg opens a viewer. Any way to key into the viewer itself?
We have a little C# startup appplication that users launch to run the latest version of our main C# WinForms application from a network share. It's kind of a simplified ClickOnce arrangement (our IT folks won't allow us to use ClickOnce).
The startup application exits after calling Process.Start("MainApplication.exe"), but the main application can take several seconds to display, leaving the user with a blank screen.
Is there a way that the starup application can poll the OS to find out if the main aplication is running before it exits? Or some other way to handle this?
You can use Process.WaitForInputIdle() to wait until your application enteres the Idle state.
Process appProcess = Process.Start("MainApplication.exe");
appProcess.WaitForInputIdle();
From MSDN:
...you have just started a process and
want to use its main window handle,
consider using the WaitForInputIdle
method to allow the process to finish
starting, ensuring that the main
window handle has been created
Remarks Section from Process.MainWindowHandle property.
You can call Process.GetProcessByName to see if the new process has been created. The other option would be to have your main application kill the startup application once it has finished loading.
Use Davids' suggestion or alternatively you can put a splash screen in your main application. It will be just a simple Form with an image running on a separate worker thread. Put this as the first item invoked on start up. Your app can continue initializing on the main thread & after some seconds or just before your Main app finishes initialization kill the worker thread.
One way to solve this easily is to use a global event to signal the startup application that the main app has reached a predetermined state. To do this create a named event handle in the startup application and wait for it to be signaled:
static void Main(string[] args)
{
const string globalName = "MyProgramName";//something unique
bool isNew = false;
ManualResetEvent mreExited = new ManualResetEvent(false);
EventWaitHandle mreStarted = new EventWaitHandle(false, EventResetMode.ManualReset, globalName, out isNew);
try
{
if (!isNew)//already running, just exit?
return;
//start and monitor for exit
Process pstarted = Process.Start("...");
pstarted.Exited += delegate(object o, EventArgs e) { mreExited.Set(); };
pstarted.EnableRaisingEvents = true;
int index = WaitHandle.WaitAny(new WaitHandle[] { mreExited, mreStarted });
if (index == 0)//mreExited signaled
throw new ApplicationException("Failed to start application.");
}
finally
{
mreExited.Close();
mreStarted.Close();
}
}
Then in the main program you signal the event once your ready for the startup application to quit:
static void Main(string[] args)
{
const string globalName = "MyProgramName";//same unique name
bool isNew = false;
EventWaitHandle mreStarted = new EventWaitHandle(false, EventResetMode.ManualReset, globalName, out isNew);
try
{
if (!isNew)
mreStarted.Set();
Application.Run(new Form());
}
finally
{
mreStarted.Close();
}
}
I think David's second option is the way to go here. The process may be running with no visible UI yet. So, once the main form is displayed in the second app, kill the first process. You could even, conceivably, pass the process id of the original process in via StartInfo when you start the new process.
There are many trade-offs involved in this, but you may be able to make start-up time fast enough to make this issue moot by using NGEN.
My suggestion is to put Splash Screen in your application it gives you a good feel rather than if you dont want to use Splash screen then kill the process when loading is finished. Or you can use Process.GetProcessByName()
For Splash Screen just make a Window Screen and in startup class just inherit the class from Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase that gives you a method OnCreateSplashScreen() Override this method like this :-
protected override void OnCreateSplashScreen()
{
base.OnCreateSplashScreen();
//yourSplashScreen is the screen you made as a window form either it would be a image or form
SplashScreen = yourSplashScreen();
}
Thanks ...Saurabh Singh Happy To Code
Developing a C# .NET 2.0 WinForm Application. Need the application to close and restart itself.
Application.Restart();
The above method has proven to be unreliable.
What is a better way to restart the application?
A much simpler approach that worked for me is:
Application.Restart();
Environment.Exit(0);
This preserves the command-line arguments and works despite event handlers that would normally prevent the application from closing.
The Restart() call tries to exit, starts a new instance anyway and returns. The Exit() call then terminates the process without giving any event handlers a chance to run. There is a very brief period in which both processes are running, which is not a problem in my case, but maybe in other cases.
The exit code 0 in Environment.Exit(0); specifies a clean shutdown. You can also exit with 1 to specify an error occurred.
If you are in main app form try to use
System.Diagnostics.Process.Start( Application.ExecutablePath); // to start new instance of application
this.Close(); //to turn off current app
Unfortunately you can't use Process.Start() to start an instance of the currently running process. According to the Process.Start() docs:
"If the process is already running, no additional process resource is started..."
This technique will work fine under the VS debugger (because VS does some kind of magic that causes Process.Start to think the process is not already running), but will fail when not run under the debugger. (Note that this may be OS-specific - I seem to remember that in some of my testing, it worked on either XP or Vista, but I may just be remembering running it under the debugger.)
This technique is exactly the one used by the last programmer on the project on which I'm currently working, and I've been trying to find a workaround for this for quite some time. So far, I've only found one solution, and it just feels dirty and kludgy to me: start a 2nd application, that waits in the background for the first application to terminate, then re-launches the 1st application. I'm sure it would work, but, yuck.
Edit: Using a 2nd application works. All I did in the second app was:
static void RestartApp(int pid, string applicationName )
{
// Wait for the process to terminate
Process process = null;
try
{
process = Process.GetProcessById(pid);
process.WaitForExit(1000);
}
catch (ArgumentException ex)
{
// ArgumentException to indicate that the
// process doesn't exist? LAME!!
}
Process.Start(applicationName, "");
}
(This is a very simplified example. The real code has lots of sanity checking, error handling, etc)
I might be late to the party but here is my simple solution and it works like a charm with every application I have:
try
{
//run the program again and close this one
Process.Start(Application.StartupPath + "\\blabla.exe");
//or you can use Application.ExecutablePath
//close this one
Process.GetCurrentProcess().Kill();
}
catch
{ }
I had the same exact problem and I too had a requirement to prevent duplicate instances - I propose an alternative solution to the one HiredMind is proposing (which will work fine).
What I am doing is starting the new process with the processId of the old process (the one that triggers the restart) as a cmd line argument:
// Shut down the current app instance.
Application.Exit();
// Restart the app passing "/restart [processId]" as cmd line args
Process.Start(Application.ExecutablePath, "/restart" + Process.GetCurrentProcess().Id);
Then when the new app starts I first parse the cm line args and check if the restart flag is there with a processId, then wait for that process to Exit:
if (_isRestart)
{
try
{
// get old process and wait UP TO 5 secs then give up!
Process oldProcess = Process.GetProcessById(_restartProcessId);
oldProcess.WaitForExit(5000);
}
catch (Exception ex)
{
// the process did not exist - probably already closed!
//TODO: --> LOG
}
}
I am obviously not showing all the safety checks that I have in place etc.
Even if not ideal - I find this a valid alternative so that you don't have to have in place a separate app just to handle restart.
Start/Exit Method
// Get the parameters/arguments passed to program if any
string arguments = string.Empty;
string[] args = Environment.GetCommandLineArgs();
for (int i = 1; i < args.Length; i++) // args[0] is always exe path/filename
arguments += args[i] + " ";
// Restart current application, with same arguments/parameters
Application.Exit();
System.Diagnostics.Process.Start(Application.ExecutablePath, arguments);
This seems to work better than Application.Restart();
Not sure how this handles if your program protects against multiple instance. My guess is you would be better off launching a second .exe which pauses and then starts your main application for you.
It's simple, you just need to call the Application.Restart() method, this will invoke your application to be restarted. You must also exit from the local environment with an error code:
Application.Restart();
Environment.Exit(int errorcode);
You can create an enumeration of error codes so that you application will exit efficeintly.
Another method is to just exit from the application and start the process using the executable path:
Application.Exit();
System.Diagnostics.Process.Start(Application.ExecutablePath);
Try this code:
bool appNotRestarted = true;
This code must also be in the function:
if (appNotRestarted == true) {
appNotRestarted = false;
Application.Restart();
Application.ExitThread();
}
I figured an another solution out, perhaps anyone can use it, too.
string batchContent = "/c \"#ECHO OFF & timeout /t 6 > nul & start \"\" \"$[APPPATH]$\" & exit\"";
batchContent = batchContent.Replace("$[APPPATH]$", Application.ExecutablePath);
Process.Start("cmd", batchContent);
Application.Exit();
Code is simplified so take care of Exceptions and stuff ;)
I fear that restarting the entire application using Process is approaching your problem in the wrong way.
An easier way is to modify the Program.cs file to restart:
static bool restart = true; // A variable that is accessible from program
static int restartCount = 0; // Count the number of restarts
static int maxRestarts = 3; // Maximum restarts before quitting the program
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
while (restart && restartCount < maxRestarts)
{
restart = false; // if you like.. the program can set it to true again
restartCount++; // mark another restart,
// if you want to limit the number of restarts
// this is useful if your program is crashing on
// startup and cannot close normally as it will avoid
// a potential infinite loop
try {
Application.Run(new YourMainForm());
}
catch { // Application has crashed
restart = true;
}
}
}
You are forgetting the command-line options/parameters that were passed in to your currently running instance. If you don't pass those in, you are not doing a real restart. Set the Process.StartInfo with a clone of your process' parameters, then do a start.
For example, if your process was started as myexe -f -nosplash myfile.txt, your method would only execute myexe without all those flags and parameters.
I wanted the new application start up after the old one shuts down.
Using process.WaitForExit() to wait for your own process to shutdown makes no sense. It will always time out.
So, my approach is to use Application.Exit() then wait, but allow events to be processed, for a period of time. Then start a new application with the same arguments as the old.
static void restartApp() {
string commandLineArgs = getCommandLineArgs();
string exePath = Application.ExecutablePath;
try {
Application.Exit();
wait_allowingEvents( 1000 );
} catch( ArgumentException ex ) {
throw;
}
Process.Start( exePath, commandLineArgs );
}
static string getCommandLineArgs() {
Queue<string> args = new Queue<string>( Environment.GetCommandLineArgs() );
args.Dequeue(); // args[0] is always exe path/filename
return string.Join( " ", args.ToArray() );
}
static void wait_allowingEvents( int durationMS ) {
DateTime start = DateTime.Now;
do {
Application.DoEvents();
} while( start.Subtract( DateTime.Now ).TotalMilliseconds > durationMS );
}
You could also use Restarter.
Restarter is an application that automatically monitor and restarts crashed or hung programs and applications. It was originally developed to monitor and restart game servers, but it will do the job for any console or form based program or application
public static void appReloader()
{
//Start a new instance of the current program
Process.Start(Application.ExecutablePath);
//close the current application process
Process.GetCurrentProcess().Kill();
}
Application.ExecutablePath returns your aplication .exe file path
Please follow the order of calls. You might want to place it in a try-catch clause.
The problem of using Application.Restart() is, that it starts a new process but the "old" one is still remaining. Therefor I decided to Kill the old process by using the following code snippet:
if(Condition){
Application.Restart();
Process.GetCurrentProcess().Kill();
}
And it works proper good. In my case MATLAB and a C# Application are sharing the same SQLite database. If MATLAB is using the database, the Form-App should restart (+Countdown) again, until MATLAB reset its busy bit in the database. (Just for side information)
How about create a bat file, run the batch file before closing, and then close the current instance.
The batch file does this:
wait in a loop to check whether the process has exited.
start the process.
Here's my 2 cents:
The sequence Start New Instance->Close Current Instance should work even for the applications that don't allow running multiple copies simultaneously as in this case the new instance may be passed a command-line argument which will indicate that there is a restart in progress so checking for other instances running will not be necessary. Waiting for the first instance to actually finish my be implemented too if it's absolutely imperative that no two intstances are running in parallel.
Application.Restart();
Environment.Exit(0);
I had a similar problem, but mine was related to unmanageable memory leak that I couldn't find on an app that has to run 24/7. With the customer I agreed that safe time to restart the app was 03:00AM if the memory consumption was over the defined value.
I tried Application.Restart, but since it seems to use some mechanism that starts new instance while it is already running, I went for another scheme. I used the trick that file system handles persist until process that created them dies. So, from The Application, i dropped the file to the disk, and didn't Dispose() the handle. I used the file to send 'myself' executable and starting directory also (to add flexibility).
Code:
_restartInProgress = true;
string dropFilename = Path.Combine(Application.StartupPath, "restart.dat");
StreamWriter sw = new StreamWriter(new FileStream(dropFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite));
sw.WriteLine(Application.ExecutablePath);
sw.WriteLine(Application.StartupPath);
sw.Flush();
Process.Start(new ProcessStartInfo
{
FileName = Path.Combine(Application.StartupPath, "VideoPhill.Restarter.exe"),
WorkingDirectory = Application.StartupPath,
Arguments = string.Format("\"{0}\"", dropFilename)
});
Close();
Close() at the end would initiate app shutdown, and file handle I used for StreamWriter here would be held open until process really dies. Then...
Restarter.exe comes into action. It TRIES to read the file in exclusive mode, preventing it to gain access until main app wasn't dead, then starts main app, deletes the file and exists. I guess that it can't be simpler:
static void Main(string[] args)
{
string filename = args[0];
DateTime start = DateTime.Now;
bool done = false;
while ((DateTime.Now - start).TotalSeconds < 30 && !done)
{
try
{
StreamReader sr = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));
string[] runData = new string[2];
runData[0] = sr.ReadLine();
runData[1] = sr.ReadLine();
Thread.Sleep(1000);
Process.Start(new ProcessStartInfo { FileName = runData[0], WorkingDirectory = runData[1] });
sr.Dispose();
File.Delete(filename);
done = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Thread.Sleep(1000);
}
}
I use the following and it does exactly what you are looking for:
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
UpdateCheckInfo info = null;
info = ad.CheckForDetailedUpdate();
if (info.IsUpdateRequired)
{
ad.UpdateAsync(); // I like the update dialog
MessageBox.Show("Application was upgraded and will now restart.");
Environment.Exit(0);
}
for using As logout you need to terminate all app from Ram Cache
so close The Application first and then Rerun it
//on clicking Logout Button
foreach(Form frm in Application.OpenForms.Cast<Form>().ToList())
{
frm.Close();
}
System.Diagnostics.Process.Start(Application.ExecutablePath);
You could enclose your code inside a function and when restart is needed you can just call the function.
Take for instance an application that:
While application is not registered; (upon start) the application should prompt the user to register the application and create a login account.
Once registration is submitted and login credentials are created; the application should restart, check for registration and prompt the user to login with the inserted credentials (so the user can access to all the application features).
Problem:
By building and launching the application from Visual Studio; any of the 4 alternatives bellow will fail to accomplish the tasks required.
/*
* Note(s):
* Take into consideration that the lines bellow don't represent a code block.
* They are just a representation of possibilities,
* that can be used to restart the application.
*/
Application.Restart();
Application.Exit();
Environment.Exit(int errorCode);
Process.GetCurrentProcess().Kill();
What happens is: After creating the Registration, Login and calling Application.Restart(); the application will (strangely) reopen the Registration Form and skip data in a Database (even though the resource is set to "Copy if Newer").
Solution:
Batch Building the application was (for me) a proof that any of the lines above were actually working as expected.
Just not when building and running the application with Visual Studio.
In first place I'd try batch building the application; run it outside Visual Studio and check if Application.Restart() actually works as expected.
Also Check further Info regarding this thread subject:
How do I restart my C# WinForm Application?
I've found a new way that's pretty convenient and has quite a few upsides.
There's never more than one instance running.
Command line args are persisted.
No exit events are raised from the application.
No process handles are broken.
I had a third party application managing my application with Process.Start and using Exit event to reload the application. Many of these solutions would break this implementation which is how I ended up on the following solution.
public static CancellationTokenSource _restartTokenSource;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
while (_restartTokenSource == null || _restartTokenSource.IsCancellationRequested)
{
_restartTokenSource = new System.Threading.CancellationTokenSource();
_restartTokenSource.Token.Register(() =>
{
foreach (Form form in Application.OpenForms)
form.Close();
});
Application.Run(new FlashMain(args));
}
}
Since Application.Run blocks until all forms in the application are closed I put this portion of the initialization into a loop that only executes when a CancellationTokenSource is null (the first run) or IsCancellationRequested is true (restart requested).
I register an event on the CancellationTokenSource that closes all forms in the application when .Cancel() is called, therefore unblocking Application.Run and restarting the loop.
Call Program._restartTokenSource.Cancel(); anywhere in the application to restart it.
P.S. This also works great for injecting into a BlazorWebView to restart the application from .NET Core.