2

I have restricted my C# windows application to only allow one instance to be running at a time, using this question How to force C# .net app to run only one instance in Windows?

It works well and does not allow more than one instance of the application to run at the same time.

The problem is that if the user attempts to open a second instance of the application, I want the currently active one to come to the front.

The question I worked from seems to address this, but it is not working for me.

I think it is because my application is not meeting the criteria to allow the method :SetForegroundWindow to work.

My question is, how can I achieve this. My code is below:

using System    ;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace RTRFIDListener_Client
{
    static class Program
    {
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool SetForegroundWindow(IntPtr hWnd);

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            bool createdNew = true;

            using (Mutex mutex = new Mutex(true, "RTRFIDListener_Client", out createdNew))
            {
                if (createdNew)
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new frm_Main());
                }
                else
                {
                    Process current = Process.GetCurrentProcess();
                    foreach (Process process in Process.GetProcessesByName(current.ProcessName))
                    {
                        if (process.Id != current.Id)
                        {
                            SetForegroundWindow(process.MainWindowHandle);
                            break;
                        }
                    }
                }
            }
        }
    }
}
Community
  • 1
  • 1
Alex
  • 3,730
  • 9
  • 43
  • 94
  • The answer in the marked duplicate addresses this (via a broadcast message) http://stackoverflow.com/questions/19147/what-is-the-correct-way-to-create-a-single-instance-application – Alex K. Mar 25 '15 at 15:42
  • It works for me. I can't see any problem. – Vano Maisuradze Mar 25 '15 at 15:53
  • @AlexK. it works fine if the application has been minimised and is still running, but if it has been closed and is still running in the background then it does not work – Alex Mar 25 '15 at 15:55
  • @VanoMaisuradze see above comment – Alex Mar 25 '15 at 15:55
  • If the main window of previous instance has been closed, there is nothing to bring to the foreground. Isn't it? – Dmitry Mar 25 '15 at 15:59
  • @Dmitry no that is not that case, the appliction is still running in the background – Alex Mar 25 '15 at 16:02

2 Answers2

6

Spinning your own single-instance app is generally a mistake, the .NET Framework already supports it strongly and it is rock-solid, very hard to exploit. And has the feature you are looking for, a StartupNextInstance event that fires when the user starts your app again. Add a reference to Microsoft.VisualBasic and make your Program.cs file look like this:

using System;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;

namespace WhatEverYouUse {
    class Program : WindowsFormsApplicationBase {
        [STAThread]
        static void Main(string[] args) {
            Application.SetCompatibleTextRenderingDefault(false);
            new Program().Start(args);
        }
        void Start(string[] args) {
            this.EnableVisualStyles = true;
            this.IsSingleInstance = true;
            this.MainForm = new Form1();
            this.Run(args);
        }
        protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs) {
            eventArgs.BringToForeground = true;
            base.OnStartupNextInstance(eventArgs);
        }
    }
}

If you have any use for the command line arguments that were used to start the 2nd instance, typical when you use a file association for example, then use eventArgs.CommandLine in your event handler.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
0

try this...

System.Threading.Tasks.Task.Factory.StartNew(() => { SetForegroundWindow(this.Handle); });
sam byte
  • 697
  • 9
  • 11
  • 1
    Please add to your answer some explanation on why and how this fixes the problem. Code only answers are not good fit for SO. This answer may be deleted. – Alexander Trakhimenok Nov 20 '17 at 14:01
  • Please add some context to your answer. Code only answeres are not considered to be good style on SO. Why does this solve the problem? – Neuron Nov 20 '17 at 14:01