1

I am familiar with WPF application but completely new to Winforms.

The objective is to create a single instance Winforms application. If another instance instantiated, it should notify the main instance with corresponding command args that will invoke action on main instance. Here is the sample that will work on WPF.

I have achieved the same in WPF using the MSDN helper. But when I try to make use of the same in Winforms, I could not resolve the following things.

  • Application instance missing in Winforms.
  • Application.Currentis missing that will be used to invoke the main instance.

Is there any equivalent in winforms, or any other way to achieve the similar functionality in Winforms.

Gopichandar
  • 2,742
  • 2
  • 24
  • 54

3 Answers3

2

The idea is to use a Mutex to detect an instance is already running. To communicate with the first instance, you can use IPC (inter process communication). Here's the code:

static class Program
{
    const string AppId = "Local\\1DDFB948-19F1-417C-903D-BE05335DB8A4"; // Unique par application 

    [STAThread]
    static void Main(string[] args)
    {
        using (var mutex = new Mutex(false, AppId))
        {
            if (!mutex.WaitOne(0))
            {
                // 2nd instance
                // Send the command line to the first instance
                IpcChannel clientChannel = new IpcChannel();
                ChannelServices.RegisterChannel(clientChannel, false);
                SingleInstance app = (SingleInstance)Activator.GetObject(typeof(SingleInstance), string.Format("ipc://{0}/RemotingServer", AppId));
                app.Execute(args);
                return;
            }

            // 1st instance

            // Register the IPC server
            IpcChannel channel = new IpcChannel(AppId);
            ChannelServices.RegisterChannel(channel, false);
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(SingleInstance), "RemotingServer", WellKnownObjectMode.Singleton);

            // Start the application
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

    private class SingleInstance : MarshalByRefObject
    {
        public void Execute(string[] args)
        {
            // TODO use the args sent by the second instance
        }
    }
}
meziantou
  • 20,589
  • 7
  • 64
  • 83
0

Documentation on MSDN: https://msdn.microsoft.com/en-us/library/f55ddskf(v=vs.110).aspx

Short how-to

  • In the startup of the application, create/open a Mutex with a unique name (it's scope is global/system

var mutex = new Mutex(false, "My awesome single-instance project");

  • Check if the Mutex is already taken/controlleed

var isMutexControlled = mutex.WaitOne(0, false);

  • If it is already controlled, exit the application.

For more in-depth, community knowledge, look at this answer which provides a robust way to create a Mutex: What is a good pattern for using a Global Mutex in C#?

Bonus Q&A

Q: Why is Application or Application.Current not available or null?

A: It is a System.Windows.Application.Current is only found in the WPF libraries, not in the Windows Forms libraries. They are separate frameworks of building a visual application (though they can be combined but let's not go down that rabbit hole).

Community
  • 1
  • 1
M. Mimpen
  • 1,212
  • 16
  • 21
0

You could use a global Mutex like this: https://stackoverflow.com/a/1213517

Or use a Windows event like in this answer : https://stackoverflow.com/a/646500

FatalJamòn
  • 386
  • 2
  • 10