Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I enforce a single instance of my application?

How can I ensure a single instance of my application and to set the focus to it when attempting to open a second instance?

I tried:

public partial class Form1 : Form {

    [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
    public static extern
    IntPtr FindWindow(String lpClassName, String lpWindowName);

    [DllImport("USER32.DLL")]
    public static extern
    Boolean SetForegroundWindow(IntPtr hWnd);

    private void Form1_Load(object sender, EventArgs e)
    {
        bool isRunning = Process.GetProcesses()
                                .Where(p => p.MainWindowTitle.Contains(Text))
                                .Count() > 1;

        if (isRunning)
        {
            FocusWindow(Text);
            Application.Exit();
        }
    }

    public static void FocusWindow(string title)
    {
        SetForegroundWindow(FindWindow(null, title));
    }
}

This is not focusing the application. How can I fix this?

like image 563
Jack Avatar asked Dec 27 '22 07:12

Jack


2 Answers

You may want to use Mutex instead, which avoids to search for windows in a slightly unreliable way (imagine you rename your main form or open another form instead).

bool createdNew;
Mutex m = new Mutex(true, "SomeNameHere", out createdNew);

if (!createdNew)
{
    // Application already running. Call it and ask to show it's form.
    IpcClientChannel clientChannel = new IpcClientChannel();
    ChannelServices.RegisterChannel(clientChannel, true);

    RemotingConfiguration.RegisterWellKnownClientType(typeof(ExchangeBase), "ipc://SomeNameHere/YourAppBase");

    ExchangeBase Exchange = new ExchangeBase();
    Exchange.ShowForm();
}
else
{
    IpcServerChannel serverChannel = new IpcServerChannel("SomeNameHere");
    ChannelServices.RegisterChannel(serverChannel, true);
    RemotingConfiguration.RegisterWellKnownServiceType(typeof(ExchangeBase), "YourAppBase", WellKnownObjectMode.SingleCall);

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    MainForm = new FormMain();
    if (!MainForm.StopLoading)
    {
        Application.Run(MainForm);

        // Keep the mutex reference alive until the termination of the program.
        GC.KeepAlive(m);
    }
}
like image 63
Arseni Mourzenko Avatar answered Dec 29 '22 20:12

Arseni Mourzenko


It looks like you're passing Text as a parameter to your FocusWindow method, but while doing a Contains check. I'll bet the Text is only a partial window title and thus, causing FindWindow to fail. Try passing the full text of the window handle instead like:

var proc = Process.GetProcesses()
                  .Where(p => p.MainWindowTitle.Contains(Text))
                  .FirstOrDefault();

        if (proc != null)
        {
            FocusWindow(p.MainWindowTitle);
            Application.Exit();
        }
like image 25
Steve Danner Avatar answered Dec 29 '22 21:12

Steve Danner