views:

278

answers:

4

When I call the Application.Restart() method, the error comes up that detects whether the application is currently running. Is there anyway around this?

    static void Main(string[] args)
    {
        string proc = Process.GetCurrentProcess().ProcessName;
        Process[] processes = Process.GetProcessesByName(proc);
        if (processes.Length > 1)
        {
            MessageBox.Show("Program is already running.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        else
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
A: 

The simplest way to do this is to add a delay before quiting.

In other words,

string proc = Process.GetCurrentProcess().ProcessName;
if (Process.GetProcessesByName(proc).Length > 1) {
    Thread.Sleep(500);      //500 milliseconds; you might need to wait longer
    if (Process.GetProcessesByName(proc).Length > 1) {
        MessageBox.Show("Program is already running.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }
}    //no else
SLaks
Why was this downvoted?
SLaks
Sorry for the down vote, but polling with a Sleep is really ugly. I wouldn't recommend it for any purpose.
Bob Nadler
I didn't say it was the best; I said it was the simplest. The best solution is my other answer.
SLaks
Upvoted for the idea, it was better than nothing. But I will use Mutex instead.
Nate Shoffner
A: 

Try hooking up your restart code to the Application.ApplicationExit event as a listener method. Then you will call Application.Exit to cause the code to run indirectly.

Edit: Added code sample:

For example, when the user clicks the restart button or the app decides to restart, call this RestartMeSmartly() method. You won't have to worry about trickery - it will work.

void RestartMeSmartly() {
    Application.ApplicationExit += BeforeExiting;
    Application.Exit();
}

void BeforeExiting(object sender, EventArgs args) {
    Application.Restart();
}
John K
Actually, it would be better to conditionally restart the program at the end of the `Main` method, which is the last managed code executed by the program. (except finalizers) However, even so, it would be non-deterministic and I wouldn't recommend it.
SLaks
How do we know that the Application.ApplicationExit event isn't called at the end of Main method or even later by the runtime? Maybe ApplicationExit is better.
John K
Application.Exit is called when the message loop exits, during the call to Application.Run.
SLaks
+3  A: 

Use a Mutex. e.g.: A Single Instance Application which Minimizes to the System Tray when Closed. This example is more complex than you probably need, but the basic single instance concept of using a Mutex works well.

Bob Nadler
This is how VB's `IsSingleInstance` property works, as in my second answer.
SLaks
+1  A: 

The most effective way to do this is to inherit from VB.Net's WindowsFormsApplicationBase class, which can also be used in C#, and set the IsSingleInstance property to true. This uses a mutex and will continue working if the EXE file is renamed.

SLaks