views:

291

answers:

4

I want to create a program that uses ClickOnce for installation and registers a file-association, and always only starts a single instance, so that if a file of that file extension is clicked again it will be sent to the first (already opened) program.

Does anybody know of a good code-example of how to do that ?

Please keep in mind the ClickOnce part - because that changes how one should handle the SingleInstance bit.

+1  A: 

I guess this will help you: http://www.openwinforms.com/single_instance_application.html

Carl Hörberg
Thanks, but this completely ignores the ClickOnce aspect!
Pygmy
ok :( what is different with ClickOnce applications in that aspect?
Carl Hörberg
That a ClickOnce application starts the executable in a different way which can include auto-updates and passes parameters in a different way, as far as I've been able to figure out... But I'm not sure what all of this means for the SingleInstance stuff, which is why I'm asking this question :)
Pygmy
the problems seems to be solved here: http://stackoverflow.com/questions/248721/how-can-i-build-a-single-instance-application-using-click-once
Carl Hörberg
A: 

You could do something similar to this:

using System.Diagnostics;

    namespace Foo

    {

        class Bar

        {

            static void Main(string[] args)

            {

                Process p = Process.GetCurrentProcess();

                Process [] processSearch = Process.GetProcessesByName(p.ProcessName);

                if (processSearch.Length > 1)

                {

                    return;

                }

            }
         }
    }
Benjamin Ortuzar
Checking by process name only leads to simplistic DoS attacks. You should use a mutex.
Cory Charlton
A: 

You should use a Mutex to check if you application is running:

    static void Main()
    {
        bool createdNew;

        using (Mutex mutex = new Mutex(true, Application.ProductName, out createdNew))
        {
            mutex.ReleaseMutex();
            if (createdNew)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new FormMain());
            }
            else
            {
                using (Process currentProcess = Process.GetCurrentProcess())
                {
                    foreach (Process process in Process.GetProcessesByName(currentProcess.ProcessName))
                    {
                        if (process.Id != currentProcess.Id)
                        {
                            User32.SetForegroundWindow(process.MainWindowHandle);
                            break;
                        }
                    }
                }
            }
        }
    }

The SetForegroundWindow:

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool SetForegroundWindow(IntPtr hWnd);
Cory Charlton