sooprise
sooprise

Reputation: 23187

WinForm Application Restart?

I have an application that runs on my computer and the computers of my colleagues at work. I sometimes push out updates for this application and want the application to detect this automatically (perhaps via database) and shut down and re-open to install the new updates.

I know how I can close an application, but don't know how I can re-open it because when it's not running, I don't know how to execute any code...

Upvotes: 2

Views: 2041

Answers (5)

Daniel Mošmondor
Daniel Mošmondor

Reputation: 19956

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

Upvotes: 0

fletcher
fletcher

Reputation: 13750

ClickOnce handles updating an application very well. I don't see a problem here, if the user finds that the application is not working (because you have made a change server-side, that warrants them to update the client), they will restart the application and be prompted by the ClickOnce update mechanism to say an update is available (if this has been set up), once the application starts again.

The only way you could tell whether the application was due for an update, whilst the application in question is still running, is to poll the ClickOnce deployment file on the server and compare the version number against the current deployment. Not advisable.

Edit:

Another way to ensure that your users always have the most up-to-date version, is to not include a persistent deployment file and make the user always run from the launch page on your website. This would only dish out the latest and greatest version.

Upvotes: 3

Peter Kelly
Peter Kelly

Reputation: 14391

If you are using ClickOnce (and your tag suggests you are?) then you can configure it so your application checks for updates on start-up.

Upvotes: 0

Rob
Rob

Reputation: 45771

The process you really need to have is something like this:

  1. Application detects an update is required and executes an Update Application and then exits itself
  2. Update application downloads and installs the update
  3. Update application restarts the "main" application

The "Update application" may need administrative privileges to run if you're updating files on a Vista/Windows7 machine due to UAC, so you'd probably want to embed a manifest to help solve that.

To start another process, the code you'll want to execute is System.Diagnostics.Process.Start(), for example:

Process p = new Process();
p.StartInfo.FileName = "C:\\Windows\\System32\cmd.exe";
p.Start();

Upvotes: 1

James Gaunt
James Gaunt

Reputation: 14783

How about creating a small update app. When your application detects an update it launches the update app and closes itself. The update app downloads and installs the update and then relaunches the main app and closes itself.

Alternatively if the application can update itself when it opens, why does it need to shutdown? Can't it just release any resources it's using etc and perform the update.

Upvotes: 1

Related Questions