Clack
Clack

Reputation: 945

Single instance windows forms application and how to get reference on it?

I have a Windows Forms application that allows only one instance to be running at the time. I have implemented Singleton by using Mutex. The Application must be startable from commandline (with or without parameters). Application is started and exited by script. User can not take any action on it.

So, application purpose is simple "indicator" application that will just display some visual and graphical information for the enduser. End user can not do anything with it, just see it. It is windows forms application because then visual and graphical appearance is relatively easy implement (you can get it topmost, borderless, etc.).

To put it simply: How can I exit the current running application when someone tries to run same application with exit commandline parameter?

bool quit = (args.Length > 0 && args[0] == "quit") ? true : false;
using (Mutex mutex = new Mutex(false, sExeName))
{
    if (!mutex.WaitOne(0, true)) 
    {
        if (quit)
        {
            // This is the tricky part?
            // How can I get reference to "previous" launced 
            // Windows Forms application and call it's Exit() method.
        }
    } 
    else 
    {
        if (!quit)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

Upvotes: 5

Views: 8894

Answers (4)

Khalid Rafique
Khalid Rafique

Reputation: 161

I think the easiest way is the following

see the link

http://codenicely.blogspot.com/2010/04/creating-forms-object.html

Upvotes: 0

Hans Passant
Hans Passant

Reputation: 942267

The .NET framework offers a very good generic solution for this. Check the bottom of this MSDN magazine article. Use the StartupNextInstanceHandler() event handler to pass arbitrary commands to the running instance, like "quit".

Upvotes: 6

Tormod Fjeldskår
Tormod Fjeldskår

Reputation: 6002

This is a somewhat quick-and-dirty solution which you would probably want to refine:

[STAThread]
static void Main()
{
    var me = Process.GetCurrentProcess();
    var otherMe = Process.GetProcessesByName(me.ProcessName).Where(p => p.Id != me.Id).FirstOrDefault();

    if (otherMe != null)
    {
        otherMe.Kill();
    }
    else
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

If an instance of the app is already started, that process is killed; otherwise the app starts normally.

Upvotes: 1

Matt
Matt

Reputation: 1370

Is this not over complicating things ? Rather than closing the existing instance and starting a new one, can you not just re-activate the existing instance? Either way round the code below should give you some ideas on how to go about it...?

Process thisProcess = Process.GetCurrentProcess();
        Process[] allProcesses = Process.GetProcessesByName(thisProcess.ProcessName);
        Process otherProcess = null;
        foreach (Process p in allProcesses )
        {
            if ((p.Id != thisProcess.Id) && (p.MainModule.FileName == thisProcess.MainModule.FileName))
            {
                otherProcess = p;
                break;
            }
        }

       if (otherProcess != null)
       {
           //note IntPtr expected by API calls.
           IntPtr hWnd = otherProcess.MainWindowHandle;
           //restore if minimized
           ShowWindow(hWnd ,1);
           //bring to the front
           SetForegroundWindow (hWnd);
       }
        else
        {
            //run your app here
        }

There is another question about this here

Upvotes: 5

Related Questions