This is the code I implemented so far to create a single instance WPF application:
#region Using Directives
using System;
using System.Globalization;
using System.Reflection;
using System.Threading;
using System.Windows;
using System.Windows.Interop;
#endregion
namespace MyWPF
{
public partial class MainApplication : Application, IDisposable
{
#region Members
private Int32 m_Message;
private Mutex m_Mutex;
#endregion
#region Methods: Functions
private IntPtr HandleMessages(IntPtr handle, Int32 message, IntPtr wParameter, IntPtr lParameter, ref Boolean handled)
{
if (message == m_Message)
{
if (MainWindow.WindowState == WindowState.Minimized)
MainWindow.WindowState = WindowState.Normal;
Boolean topmost = MainWindow.Topmost;
MainWindow.Topmost = true;
MainWindow.Topmost = topmost;
}
return IntPtr.Zero;
}
private void Dispose(Boolean disposing)
{
if (disposing && (m_Mutex != null))
{
m_Mutex.ReleaseMutex();
m_Mutex.Close();
m_Mutex = null;
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
#region Methods: Overrides
protected override void OnStartup(StartupEventArgs e)
{
Assembly assembly = Assembly.GetExecutingAssembly();
Boolean mutexCreated;
String mutexName = String.Format(CultureInfo.InvariantCulture, "Local\\{{{0}}}{{{1}}}", assembly.GetType().GUID, assembly.GetName().Name);
m_Mutex = new Mutex(true, mutexName, out mutexCreated);
m_Message = NativeMethods.RegisterWindowMessage(mutexName);
if (!mutexCreated)
{
m_Mutex = null;
NativeMethods.PostMessage(NativeMethods.HWND_BROADCAST, m_Message, IntPtr.Zero, IntPtr.Zero);
Current.Shutdown();
return;
}
base.OnStartup(e);
MainWindow window = new MainWindow();
MainWindow = window;
window.Show();
HwndSource.FromHwnd((new WindowInteropHelper(window)).Handle).AddHook(new HwndSourceHook(HandleMessages));
}
protected override void OnExit(ExitEventArgs e)
{
Dispose();
base.OnExit(e);
}
#endregion
}
}
Everything works perfectly... but I have some doubts about it and I would like to receive your suggestions about how my approach could be improved.
1) I was asked by Code Analysis to implement IDisposable
interface because I was using IDisposable
members (the Mutex
). Is my Dispose()
implementation good enough? Should I avoid it because it's never going to be called?
2) It's better to use m_Mutex = new Mutex(true, mutexName, out mutexCreated);
and check for the result or to use m_Mutex = new Mutex(false, mutexName);
and then check for m_Mutex.WaitOne(TimeSpan.Zero, false);
? In case of multithreading I mean...
3) RegisterWindowMessage
API call should return UInt32
... but HwndSourceHook
is only accepting Int32
as message value... should I be worried about unexpected behaviors (like a result bigger than Int32.MaxValue
)?
4) In OnStartup
override... should I execute base.OnStartup(e);
even if another instance is already running and I'm going to shutdown the application?
5) Is there a better way to bring the existing instance to the top that doesn't need to set Topmost
value? Maybe Activate()
?
6) Can you see any flaw in my approach? Something concerning multithreading, bad exceptions handling and something like that? For example... what happens if my application crashes between OnStartup
and OnExit
?
1) It looks like a standard Dispose implementation to me. It is not really necessary (see point 6) but it does not do any harm. (Cleanup on closing it's a bit like cleaning the house before burning it down, IMHO, but opinions on the matter differs..)
Anyway, why not using "Dispose" as the name of the cleanup method, even if it does not get called directly? You could have called it "Cleanup", but remember you also write code for humans, and Dispose looks familiar and anyone on .NET understands what is it for. So, go for "Dispose".
2) I have always seen m_Mutex = new Mutex(false, mutexName);
I think it's more a convention that a technical advantage, however.
3) From MSDN:
If the message is successfully registered, the return value is a message identifier in the range 0xC000 through 0xFFFF.
So I would not worry. Usually, for this class of functions, UInt is not used for "it does not fit in Int, let's use UInt so we have something more" but to clarify a contract "function never returns a negative value".
4) I would avoid calling it if you will shutdown, same reason as #1
5) There are a couple of ways of doing it. The easiest way in Win32 is simply to have the second instance make the call to SetForegroundWindow (Look here: http://blogs.msdn.com/b/oldnewthing/archive/2009/02/20/9435239.aspx); however, I don't know if there is an equivalent WPF functionality or if you need to PInvoke it.
6)
For example... what happens if my application crashes between OnStartup and OnExit?
It's OK: when a process terminates, all handles owned by the process are released; the mutex is released as well.
In short, my recommendations:
For example, you can use your technique (trying to send/post a message to the window - if does not answer back it is stuck), plus MSK technique, to find and terminate the old process. Then start normally.