All posts in Mutex

That’s what’s up. We are going to stop windows from stealing focus with C#. No frills, no crap, no more of this nonsense. It’s time to stop.

Q: Why does Windows do this and why isn’t there a setting to fix this?
A: Remember Fred Johnson who lived down the street in the 70’s? You know… that slightly overweight jerk that bullied the smart kids? Well, one day on the way home from school he kicked Billy Gates dog and said something off color about his “parentage”. So, now we need to suffer for Fred’s sins. No need to Wiki this, it’s a true story.

 
Joking Aside

So, back in the early 2000’s we had the Windows XP PowerToy called TweakUI which allowed us to control how initialized windows interacted with the desktop environment. This involved changing the following registry key:

HKEY_CURRENT_USER\Control Panel\Desktop\Foreground\LockTimeout

In the modern versions of Windows, this override no longer works. For a long while, this left us SOL and drifting in space looking for the answer… that is until now.

 
The Solution

In my opinion, the C# community was right in thinking the best approach is to get on the P/Invoke track.

For this solution the key is LockSetForegroundWindow on a timer. For this solution we will use the following methods:


// Lock
public static uint LSFW_LOCK = 1;
public static uint LSFW_UNLOCK = 2;

/// <summary>
/// Locks the set foreground window.
/// </summary>
/// <param name="uLockCode">The u lock code.</param>
/// <returns></returns>
[DllImport("user32.dll")]
public static extern bool LockSetForegroundWindow(uint uLockCode);

/// <summary>
/// Gets the foreground window.
/// </summary>
/// <returns></returns>
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();

 
Now that we have identified the P/Invoke piece, let’s look at how we can implement this effectively with said timer in a WPF application. To do this we are going to create a controller to facilitate all our focus needs:


using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Threading;

using Win32Windows = Xcalibur.Win32.Win32ApiHelper.Windows;

namespace Xcalibur.DontInterruptMe
{
    /// <summary>
    /// Window focus controller.
    /// </summary>
    public class FocusController
    {
        #region Members
        
        private readonly DispatcherTimer _timer;
        private IntPtr _currentHandle;
        private bool _isRunning;
        private bool _isStarted;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="FocusController"/> class.
        /// </summary>
        public FocusController()
        {
            this._isRunning = false;
            this._isStarted = false;

            // Set timer
            this._timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(250) };
            this._timer.Tick += (s, e) => this.EvaluateAsync(); 

            // Start
            this.Start();
        }

        #endregion

        #region Methods

        /// <summary>
        /// Starts this instance.
        /// </summary>
        public void Start()
        {
            if (this._isStarted) return;

            // Start timer
            this._timer.IsEnabled = true;
            this._timer.Start();
            this._isStarted = true;
        }

        /// <summary>
        /// Stops this instance.
        /// </summary>
        public void Stop()
        {
            if (!this._isStarted) return;

            // Stop timer
            this._timer.Stop();
            this._timer.IsEnabled = false;
            this._isStarted = false;

            // Unlock set foreground window
            LockSetForegroundWindow(LSFW_UNLOCK);
        }

        /// <summary>
        /// Evaluates this instance.
        /// </summary>
        private void Evaluate()
        {
            if (_isRunning) return;

            // Set as "running"
            _isRunning = true;

            // Get current
            var activeWindowHandle = GetForegroundWindow();
            if (_currentHandle == activeWindowHandle)
            {
                _isRunning = false;
                return;
            }

            // Store current handle
            _currentHandle = activeWindowHandle;

            // Handle cannot be 0
            if (activeWindowHandle == IntPtr.Zero)
            {
                _isRunning = false;
                return;
            }

            // Get related process
            var processes = Process.GetProcesses();
            var currentProcess = processes.FirstOrDefault(x => x.MainWindowHandle == _currentHandle);

            // currentProcess must exist, and the MainWindowTitle must be valid.
            if (currentProcess == null || string.IsNullOrEmpty(currentProcess.MainWindowTitle))
            {
                _isRunning = false;
                return;
            }

            // Lock set foreground window
            LockSetForegroundWindow(LSFW_LOCK);

            // Set as "not running"
            _isRunning = false;
        }

        /// <summary>
        /// Evaluates the asynchronous.
        /// </summary>
        /// <returns></returns>
        private async Task EvaluateAsync()
        {
            await Task.Run(() => this.Evaluate());
        }

        #endregion

        #region P/Invoke 

        // Lock
        public static uint LSFW_LOCK = 1;
        public static uint LSFW_UNLOCK = 2;

        /// <summary>
        /// Locks the set foreground window.
        /// </summary>
        /// <param name="uLockCode">The u lock code.</param>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern bool LockSetForegroundWindow(uint uLockCode);

        /// <summary>
        /// Gets the foreground window.
        /// </summary>
        /// <returns></returns>
        [DllImport("user32.dll")]
        public static extern IntPtr GetForegroundWindow();

        #endregion
    }
}

 
The last piece is the implementation of the FocusController from App.xaml:


using System;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using Hardcodet.Wpf.TaskbarNotification;

using Microsoft.Win32;
using Application = System.Windows.Application;

namespace Xcalibur.DontInterruptMe
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        #region Members

        private static Mutex _instanceMutex;
        private FocusController _focusController;

        #endregion

        #region Methods

        /// <summary>
        /// Checks if application is already running.
        /// </summary>
        /// <returns></returns>
        private static bool StartInstance()
        {
            // Set mutex
            _instanceMutex = new Mutex(true, Constants.ApplicationKey);

            // Check if already running
            bool isAlreadyInUse = false;
            try
            {
                isAlreadyInUse = !_instanceMutex.WaitOne(TimeSpan.Zero, true);
            }
            catch (AbandonedMutexException)
            {
                KillInstance();
                isAlreadyInUse = false;
            }
            catch (Exception)
            {
                _instanceMutex.Close();
                isAlreadyInUse = false;
            }
            return isAlreadyInUse;
        }

        /// <summary>
        /// Kills the instance.
        /// </summary>
        /// <param name="code">The code.</param>
        private static void KillInstance(int code = 0)
        {
            if (_instanceMutex == null) return;

            // Owning application should release mutex
            if (code == 0)
            {
                try
                {
                    _instanceMutex.ReleaseMutex();
                }
                catch (Exception) { }
            }
            _instanceMutex.Close();
        }

        #endregion

        #region Events

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Application.Startup" /> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.StartupEventArgs" /> that contains the 
        /// event data.</param>
        protected override void OnStartup(StartupEventArgs e)
        {
            // Check if running
            if (StartInstance())
            {
                // Already running, Exit
                Current.Shutdown(1);
            }

            // Invoke focus controller
            this._focusController = new FocusController();

            // Base
            base.OnStartup(e);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Application.Exit" /> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.Windows.ExitEventArgs" /> that contains the 
        /// event data.</param>
        protected override void OnExit(ExitEventArgs e)
        {
            if (this._focusController != null)
            {
                // Gracefully exit
                this._focusController.Stop();
            }

            // Kill instance
            KillInstance(e.ApplicationExitCode);

            // Base
            base.OnExit(e);
        }

        #endregion
    }
}

 
You will notice I added the RunOnce Mutex Solution from our last post Restricting WPF Applications to run only once with a Mutex to avoid any potential issues with multiple instances.

 
Future Changes

In the next version of this application I will be tossing Process.GetProcesses() from the Evaluate method for a much faster P/Invoke solution I am planning to use in the next version of Astronomy.

If you want the complete, free product, download Don’t Interrupt Me! now.

Otherwise my friends, Happy Coding!

If you arrived here chances are you have a WPF application you want to lock down to running only once. Maybe you tried doing it by looking at Process.GetProcesses() but found it to be slow and unreliable and wanted something a bit more straight forward? Well, mutexes would be the most direct way to go. There are a few articles on the web about how to do this in .Net and they go into great detail about how mutexes work and how developers misuse them all the time. I am going to touch on the pieces you need for this solution and not waste any more of your time.

Q: What is a mutex?
A: If you took Computer Science courses this should be a no-brainer, but let’s assume you didn’t.

Mutex is short for a mutual exclusion object. This exists as a uniquely named resource that can be shared across multiple threads. Each thread would need to lock the resource to use it, so it cannot be accessed simultaneously.

Q: How does this help me?
A: Multiple applications can access the mutex allowing you to create a unique token to be reserved by a specific application instance.

Now we get to the how part.
First, let create a mutex placeholder and a unique key for our mutex:


private static Mutex _instanceMutex;
private static string MyApplicationKey = "{0036BC97-7DE3-4934-9928-43CE53CBF0AA}";

Next let’s create some key methods to set, evaluate, and terminate our mutex:


/// <summary>
/// Checks if application is already running.
/// </summary>
/// <returns></returns>
public static bool StartInstance()
{
    // Set mutex
    _instanceMutex = new Mutex(true, Constants.MyApplicationKey);

    // Check if already running
    bool isAlreadyInUse = false;
    try 
    {
        isAlreadyInUse = !_instanceMutex.WaitOne(TimeSpan.Zero, true);
    }
    catch (AbandonedMutexException)
    {
        KillInstance();
        isAlreadyInUse = false;
    }
    catch (Exception)
    {
        _instanceMutex.Close();
        isAlreadyInUse = false;
    }
    return isAlreadyInUse;
}

/// <summary>
/// Kills the instance.
/// </summary>
/// <param name="code">The code.</param>
public static void KillInstance(int code = 0)
{
    if (_instanceMutex == null) return;

    // Owning application should release mutex
    if (code == 0)
    {
        try
        {
            _instanceMutex.ReleaseMutex();
        }
        catch (Exception) { }
    }
    _instanceMutex.Close();
}

StartInstance does a few key things:

  • Claim ownership of a new mutex with our application key.
  • Evaluate the mutex by invoking a WaitHandle.
  • An AbandonedMutexException exception may occur which means the mutex exists but was not properly released by the owning process. This is likely caused by the owning process exiting unexpectedly. We kill the mutex in this case (covered later) and set this as not in use.
  • If a general exception occurs we simply close the instance and set it to not in use.
  • Otherwise, it is already in use.

 
Hold on a second!

Q: What is the difference between Releasing a mutex and Closing a mutex?
A: This is an important question.

Releasing a mutex (Mutex.ReleaseMutex()) releases a mutex from memory. This means no application can access it and it will need to be created again. Only the owning application can release the mutex unless that application is no longer in memory.

Closing a mutex (Mutex.Close()) in .Net really means closing the WaitHandle associated with the mutex. This should always be done after accessing a mutex.

 
KillInstance works as follows:

  • If a standard exit code of 0 is provided it assumes itself the owner of the mutex and attempts to release it.
  • The mutex is then closed.

 
And that’s all you need. So, let’s put it in an example.

Let’s add it to our App.xaml.cs OnStartup and OnExit as follows:


/// <summary>
/// Raises the <see cref="E:System.Windows.Application.Startup" /> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.StartupEventArgs" /> that contains the 
/// event data.</param>
protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    // Check if running
    if (!StartInstance()) return;
    
	// Apparently we are already running our app
    MessageBox.Show("Already Running!");

    // If running, peace out
    Application.Current.Shutdown(1);
}

/// <summary>
/// Raises the <see cref="E:System.Windows.Application.Exit"/> event.
/// </summary>
/// <param name="e">An <see cref="T:System.Windows.ExitEventArgs"/> that contains the event 
/// data.</param>
protected override void OnExit(ExitEventArgs e)
{
    base.OnExit(e);

    // Kill instance
    KillInstance(e.ApplicationExitCode);
}

  1. OnStartup evaluates whether the mutex is already in use. If it is, it tells the user it is already running and exits the application.
  2. OnExit passes the exit code to KillInstance and handles closing the mutex.

 
And that’s it! I recommend you read up more on mutexes to make absolutely sure you are comfortable with this approach. But for now, this should get you what you need to get back to work.

Happy coding!