Click here to Skip to main content
15,867,939 members
Please Sign up or sign in to vote.
5.00/5 (3 votes)
See more:
I use this snippet to detect if an instance of my application is already running.

C#
public static Process RunningInstance()  
 {  
    Process current = Process.GetCurrentProcess();  
    Process[] processes = Process.GetProcessesByName (current.ProcessName);  
  
     //Loop through the running processes in with the same name  
     foreach (Process process in processes)  
     {  
        //Ignore the current process  
         if (process.Id != current.Id)  
        {  
            //Make sure that the process is running from the exe file.  
             if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)  
             {  
                //Return the other process instance.  
                return process;  
             }  
         }  
     }  
     //No other instance was found, return null.  
     return null;  
 }  


However, I was thinking, is there a way to parse send the arguments in the current process to the already running process. Like in an app that adds files, I would like to kill the new process but send it's arguments to the already running process.
Posted
Comments
Rock (Multithreaded) 17-Aug-12 10:14am    
Are you want to prevent multiple execution of a same C# app?
Akinmade Bond 18-Aug-12 10:37am    
Yeah, something like that but get the arguments of the current instance sent to the already running instance.

There are many ways to do this (look up IPC mechanisms for .NET). But an increasingly common mechanism is to use WCF with named pipes. The file name is passed from the 2nd instance to the 1st instance and then the 2nd instance quits. The 1st instance knows what to do with the passed in file name (typically just open it).
 
Share this answer
 
Comments
Akinmade Bond 17-Aug-12 10:24am    
Do you have any links that I can start from? Much appreciated.
Nish Nishant 17-Aug-12 10:42am    
See http://www.codeproject.com/Articles/62934/Many-to-One-Local-IPC-using-WCF-and-NetNamedPipeBi
Akinmade Bond 17-Aug-12 11:09am    
Thank you.
Nish Nishant 17-Aug-12 11:23am    
No problem.
Wendelius 17-Aug-12 16:49pm    
Nice!
This is not a good method of detecting it. You should understand, that it's always possible that some unrelated applications can have the same name or other attributes.

Here is my method:

Use "classical" remoting based on IPC channel. Such channel uses named pipes for communication. I usually use a full file name of the location of the main executable module as a name of the channel. This way, your name is unique enough, but the same application copied in another location is considered as a different application. To me, this is fine. You can use some other unique ID, such a the one obtained from the unique name of the signed application, with very good probability of uniqueness (this strong name is even used for uniqueness in the scope of world. Another unique value can be some GUID hard-coded in the assembly or put in resources.

Now, your application should be able to play the role of both server and client part. First, it tries to put the role of the client part and connect to the server part. It if fails, the application is considered to be the only instance, and now it should act as a server. If connection is successful, this is the second instance. This second instance should use remoting via a remote object to pass, say, command-line parameter to the fist instance. The first instance's remote object accept parameters and tries to use them (for example, load more files; this is the most typical application). Also, you may want to activate the UI of the first instance, through activation of the main window or main form of the first instance. When the second instance of the application passes all the data, it close the connection and terminate itself immediately.

Results: you have only one instance of the application permanently working, others executes for a short time only, just to check in and optionally pass some data to the first instance.

—SA
 
Share this answer
 
Comments
Akinmade Bond 18-Aug-12 9:31am    
That's a very good idea, thank you.
Sergey Alexandrovich Kryukov 18-Aug-12 12:12pm    
You are welcome.
If so, please accept if formally (green button) -- thanks.
--SA
There are ways to do with few classes....

We can create a simple class to postmessage and related stuffs as :
C#
static public class WinApi
   {
       [DllImport("user32")]
       public static extern int RegisterWindowMessage(string message);

       public static int RegisterWindowMessage(string format, params object[] args)
       {
           string message = String.Format(format, args);
           return RegisterWindowMessage(message);
       }

       public const int HWND_BROADCAST = 0xffff;
       public const int SW_SHOWNORMAL = 1;

       [DllImport("user32")]
       public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

       [DllImportAttribute("user32.dll")]
       public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

       [DllImportAttribute("user32.dll")]
       public static extern bool SetForegroundWindow(IntPtr hWnd);

       public static void ShowToFront(IntPtr window)
       {
           ShowWindow(window, SW_SHOWNORMAL);
           SetForegroundWindow(window);
       }
   }


The after we need create a class to determine instances using the PostMessage...

C#
static public class SingleInstance
    {
        public static readonly int WM_SHOWFIRSTINSTANCE =
            WinApi.RegisterWindowMessage("WM_SHOWFIRSTINSTANCE|{0}", ProgramInfo.AssemblyGuid);
        static Mutex mutex;
        static public bool Start()
        {
            bool onlyInstance = false;
            string mutexName = String.Format("Local\\{0}", ProgramInfo.AssemblyGuid);

            // if you want your app to be limited to a single instance
            // across ALL SESSIONS (multiple users & terminal services), then use the following line instead:
            // string mutexName = String.Format("Global\\{0}", ProgramInfo.AssemblyGuid);

            mutex = new Mutex(true, mutexName, out onlyInstance);
            return onlyInstance;
        }
        static public void ShowFirstInstance()
        {
            WinApi.PostMessage(
                (IntPtr)WinApi.HWND_BROADCAST,
                WM_SHOWFIRSTINSTANCE,
                IntPtr.Zero,
                IntPtr.Zero);
        }
        static public void Stop()
        {
            mutex.ReleaseMutex();
        }
    }


Create a class that fetch app guid:

C#
static public class ProgramInfo
    {
        static public string AssemblyGuid
        {
            get
            {
                object[] attributes = Assembly.GetEntryAssembly().GetCustomAttributes(typeof(System.Runtime.InteropServices.GuidAttribute), false);
                if (attributes.Length == 0)
                {
                    return String.Empty;
                }
                return ((System.Runtime.InteropServices.GuidAttribute)attributes[0]).Value;
            }
        }

    }



Now we can modify the entry point as :

C#
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{

    if (!SingleInstance.Start())
    {
        SingleInstance.ShowFirstInstance();
        return;
    }

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

    try
    {

        Form1 mainForm = new Form1();
        Application.Run(mainForm);
    }
    catch (Exception e)
    {
        MessageBox.Show(e.Message);
    }

    SingleInstance.Stop();

}


Now need to add few methods to Form1(the intitial form that run from entry point:


C#
protected override void WndProc(ref Message message)
{
    if (message.Msg == SingleInstance.WM_SHOWFIRSTINSTANCE)
    {
        ShowWindow();
    }
    base.WndProc(ref message);
}

public void ShowWindow()
{
    // Insert code here to make your form show itself.
    WinApi.ShowToFront(this.Handle);
}
 
Share this answer
 
v2
Comments
Akinmade Bond 18-Aug-12 9:33am    
That works fine for Window app. Only wish there was a way to send the arguments of the new instance to the already running instance. Thanks though.
Kuthuparakkal 18-Aug-12 11:01am    
May this help you
Courtesey: http://stackoverflow.com/questions/3793997/pass-arguments-to-running-application

static class Program
{
[STAThread]
static void Main(params string[] Arguments)
{
SingleInstanceApplication.Run(new ControlPanel(), NewInstanceHandler);
}

public static void NewInstanceHandler(object sender, StartupNextInstanceEventArgs e)
{
string imageLocation = e.CommandLine[1];
MessageBox.Show(imageLocation);
e.BringToForeground = false;
ControlPanel.uploadImage(imageLocation);
}

public class SingleInstanceApplication : WindowsFormsApplicationBase
{
private SingleInstanceApplication()
{
base.IsSingleInstance = true;
}

public static void Run(Form f, StartupNextInstanceEventHandler startupHandler)
{
SingleInstanceApplication app = new SingleInstanceApplication();
app.MainForm = f;
app.StartupNextInstance += startupHandler;
app.Run(Environment.GetCommandLineArgs());
}
}
}
Akinmade Bond 22-Aug-12 10:00am    
Much appreciated. Thanks a lot.
Akinmade Bond 28-Aug-12 13:27pm    
Any ideas on how to achieve this in WPF? works perfectly in WinForms but I'm in a fix on how to make it work in WPF, any help would be appreciated.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900