38

How do I check if my C# Windows application is running ?

I know that I can check the process name but the name can be changed if the exe changes.

Is there any way to have a hash key or something to make my application unique?

Agent_L
  • 4,960
  • 28
  • 30
Stacker
  • 8,157
  • 18
  • 73
  • 135
  • 3
    If you want only one instance have a look at Mutex: http://stackoverflow.com/questions/819773/run-single-instance-of-an-application-using-mutex – Adrian Fâciu Jan 18 '11 at 09:05
  • there is a problem with using Mutex that way , plus sometimes i need to restart my application using Application.Restart which would conflict with the mutex pattern. – Stacker Jan 18 '11 at 09:10
  • So basically, your question is: "How can I get all of the mutex functionality without actually creating a mutex"? Why not ask how to fix whatever problems you have with using a mutex? – Cody Gray - on strike Jan 18 '11 at 10:03
  • @Cody: i guess your right,i should try to fix conflicts with mutex instead. thanks – Stacker Jan 18 '11 at 10:12

9 Answers9

46
public partial class App : System.Windows.Application
{
    public bool IsProcessOpen(string name)
    {
        foreach (Process clsProcess in Process.GetProcesses()) 
        {
            if (clsProcess.ProcessName.Contains(name))
            {
                return true;
            }
        }

        return false;
    }

    protected override void OnStartup(StartupEventArgs e)
    {
        // Get Reference to the current Process
        Process thisProc = Process.GetCurrentProcess();

        if (IsProcessOpen("name of application.exe") == false)
        {
            //System.Windows.MessageBox.Show("Application not open!");
            //System.Windows.Application.Current.Shutdown();
        }
        else
        {
            // Check how many total processes have the same name as the current one
            if (Process.GetProcessesByName(thisProc.ProcessName).Length > 1)
            {
                // If ther is more than one, than it is already running.
                System.Windows.MessageBox.Show("Application is already running.");
                System.Windows.Application.Current.Shutdown();
                return;
            }

            base.OnStartup(e);
        }
    }
John Odom
  • 1,189
  • 2
  • 20
  • 35
abramlimpin
  • 5,027
  • 11
  • 58
  • 97
  • 8
    This is fragile: `IsProcessOpen("name of application.exe")`. An executable may have changed name between the moment source code is written and the moment it is run on user's machine. Mutex don't have this problem and don't make assumption about how application is run. – Stéphane Gourichon Sep 04 '13 at 15:34
  • Is there any way to "switch to" or "bring the process to front" if another instance of application is running ? – Agent007 Dec 14 '13 at 05:38
  • Enumerate windows of the process and find the foreground one: EnumWindows. Then bring this window to the front. – izogfif Aug 28 '14 at 11:17
  • @abramlimpin App cannot derive sealed type Application – Bharath theorare Jul 22 '16 at 18:04
25

The recommended way is to use a Mutex. You can check out a sample here : http://www.codeproject.com/KB/cs/singleinstance.aspx

In specific the code:


        /// 
        /// check if given exe alread running or not
        /// 
        /// returns true if already running
        private static bool IsAlreadyRunning()
        {
            string strLoc = Assembly.GetExecutingAssembly().Location;
            FileSystemInfo fileInfo = new FileInfo(strLoc);
            string sExeName = fileInfo.Name;
            bool bCreatedNew;

            Mutex mutex = new Mutex(true, "Global\\"+sExeName, out bCreatedNew);
            if (bCreatedNew)
                mutex.ReleaseMutex();

            return !bCreatedNew;
        }
SCady
  • 445
  • 6
  • 14
basarat
  • 261,912
  • 58
  • 460
  • 511
1

For my WPF application i've defined global app id and use semaphore to handle it.

public partial class App : Application
{      
    private const string AppId = "c1d3cdb1-51ad-4c3a-bdb2-686f7dd10155";

    //Passing name associates this sempahore system wide with this name
    private readonly Semaphore instancesAllowed = new Semaphore(1, 1, AppId);

    private bool WasRunning { set; get; }

    private void OnExit(object sender, ExitEventArgs e)
    {
        //Decrement the count if app was running
        if (this.WasRunning)
        {
            this.instancesAllowed.Release();
        }
    }

    private void OnStartup(object sender, StartupEventArgs e)
    {
        //See if application is already running on the system
        if (this.instancesAllowed.WaitOne(1000))
        {
            new MainWindow().Show();
            this.WasRunning = true;
            return;
        }

        //Display
        MessageBox.Show("An instance is already running");

        //Exit out otherwise
        this.Shutdown();
    }
}
László Papp
  • 51,870
  • 39
  • 111
  • 135
SirH
  • 535
  • 2
  • 7
0

Checkout: What is a good pattern for using a Global Mutex in C#?

// unique id for global mutex - Global prefix means it is global to the machine
const string mutex_id = "Global\\{B1E7934A-F688-417f-8FCB-65C3985E9E27}";

static void Main(string[] args)
{
    using (var mutex = new Mutex(false, mutex_id))
    {
        // edited by Jeremy Wiebe to add example of setting up security for multi-user usage
        // edited by 'Marc' to work also on localized systems (don't use just "Everyone") 
        var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
        var securitySettings = new MutexSecurity();
        securitySettings.AddAccessRule(allowEveryoneRule);
        mutex.SetAccessControl(securitySettings);

        //edited by acidzombie24
        var hasHandle = false;
        try
        {
            try
            {
                // note, you may want to time out here instead of waiting forever
                //edited by acidzombie24
                //mutex.WaitOne(Timeout.Infinite, false);
                hasHandle = mutex.WaitOne(5000, false);
                if (hasHandle == false) return;//another instance exist
            }
            catch (AbandonedMutexException)
            {
                // Log the fact the mutex was abandoned in another process, it will still get aquired
            }

            // Perform your work here.
        }
        finally
        {
            //edit by acidzombie24, added if statemnet
            if (hasHandle)
                mutex.ReleaseMutex();
        }
    }
}
Community
  • 1
  • 1
KMån
  • 9,896
  • 2
  • 31
  • 41
  • 2
    -1: as the OP says, he knows he can check the process name, he wants to know what to do if the application name is changed – djeeg Jan 18 '11 at 09:10
  • @djeeg: Did we read the same question? Can you pin point where op says, *he wants to know what to do if the application name is changed*? – KMån Jan 18 '11 at 09:16
  • 6
    line number 2: "i know i can check the process name but the name can be changed if the exe changed." – djeeg Jan 18 '11 at 09:19
0

you need a way to say that "i am running" from the app,

1) open a WCF ping service 2) write to registry/file on startup and delete on shutdown 3) create a Mutex

... i prefer the WCF part because you may not clean up file/registry correctly and Mutex seems to have its own issues

Alex
  • 2,342
  • 1
  • 18
  • 30
0

Mutex and Semaphore didn't work in my case (I tried them as suggested, but it didn't do the trick in the application I developed). The answer abramlimpin provided worked for me, after I made a slight modification.

This is how I got it working finally. First, I created some helper functions:

public static class Ext
{
   private static string AssemblyFileName(this Assembly myAssembly)
    {
        string strLoc = myAssembly.Location;
        FileSystemInfo fileInfo = new FileInfo(strLoc);
        string sExeName = fileInfo.Name;
        return sExeName;
    }

    private static int HowManyTimesIsProcessRunning(string name)
    {
        int count = 0;
        name = name.ToLowerInvariant().Trim().Replace(".exe", "");
        foreach (Process clsProcess in Process.GetProcesses())
        {
            var processName = clsProcess.ProcessName.ToLowerInvariant().Trim();
            // System.Diagnostics.Debug.WriteLine(processName);
            if (processName.Contains(name))
            {
                count++;
            };
        };
        return count;
    }

    public static int HowManyTimesIsAssemblyRunning(this Assembly myAssembly)
    {
        var fileName = AssemblyFileName(myAssembly);
        return HowManyTimesIsProcessRunning(fileName);
    }
}

Then, I added the following to the main method:

[STAThread]
static void Main()
{
    const string appName = "Name of your app";

    // Check number of instances running:
    // If more than 1 instance, cancel this one.
    // Additionally, if it is the 2nd invocation, show a message and exit.
    var numberOfAppInstances = Assembly.GetExecutingAssembly().HowManyTimesIsAssemblyRunning();
    if (numberOfAppInstances == 2)
    {
       MessageBox.Show("The application is already running!
        +"\nClick OK to close this dialog, then switch to the application by using WIN + TAB keys.",
        appName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
    };
    if (numberOfAppInstances >= 2)
    {
        return;
    };
}

If you invoke the application a 3rd, 4th ... time, it does not show the warning any more and just exits immediately.

Matt
  • 25,467
  • 18
  • 120
  • 187
-1

I really simplistic way I guess would be, for every exe that is running, you could create/open a file on disk in a known location (c:\temp) with a special name "yourapp.lock" and then just count how many of those there are.

A harder way, would be to open up some inter-process communication, or sockets, so with the process list you could interrogate each process to see if it was your application.

djeeg
  • 6,685
  • 3
  • 25
  • 28
  • not acceptable as i dont think i should request access to write directly to the disk, and that would bring a lot of troubles, but thanks – Stacker Jan 18 '11 at 09:37
-1

Enter a guid in your assembly data. Add this guid to the registry. Enter a reg key where the application read it's own name and add the name as value there.

The other task watcher read the reg key and knows the app name.

YvesR
  • 5,922
  • 6
  • 43
  • 70
  • After app crash reboot will not save you from 'duplicate instance' message. Do not use registry, beware of unclean exit when you forget to remove this value – filimonic May 22 '15 at 19:20
  • Well using the registry is one option, same you do when you write a .pid file somewhere on the file system. If the applicaiton crash you need to clean this mess up. Same with the registry, the code need to handle this. – YvesR May 22 '15 at 19:37
-1

you can simply use varialbles and one file to check for running your program. when open the file contain a value and when program closes changes this value to another one.

mortaza
  • 11
  • 1