This is the code I implemented so far to create a single instance WPF application:
#region Using Directives
using System;
using System.Globalization;
using S
I wanted to have a bit better user experience - if another instance is already running let's activate it rather than showing an error about the second instance. Here is my implementation.
I use named Mutex for making sure that only one instance is running and named EventWaitHandle to pass notification from one instance to another.
App.xaml.cs:
/// Interaction logic for App.xaml
public partial class App
{
#region Constants and Fields
/// The event mutex name.
private const string UniqueEventName = "{GUID}";
/// The unique mutex name.
private const string UniqueMutexName = "{GUID}";
/// The event wait handle.
private EventWaitHandle eventWaitHandle;
/// The mutex.
private Mutex mutex;
#endregion
#region Methods
/// The app on startup.
/// The sender.
/// The e.
private void AppOnStartup(object sender, StartupEventArgs e)
{
bool isOwned;
this.mutex = new Mutex(true, UniqueMutexName, out isOwned);
this.eventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, UniqueEventName);
// So, R# would not give a warning that this variable is not used.
GC.KeepAlive(this.mutex);
if (isOwned)
{
// Spawn a thread which will be waiting for our event
var thread = new Thread(
() =>
{
while (this.eventWaitHandle.WaitOne())
{
Current.Dispatcher.BeginInvoke(
(Action)(() => ((MainWindow)Current.MainWindow).BringToForeground()));
}
});
// It is important mark it as background otherwise it will prevent app from exiting.
thread.IsBackground = true;
thread.Start();
return;
}
// Notify other instance so it could bring itself to foreground.
this.eventWaitHandle.Set();
// Terminate this instance.
this.Shutdown();
}
#endregion
}
And BringToForeground in MainWindow.cs:
/// Brings main window to foreground.
public void BringToForeground()
{
if (this.WindowState == WindowState.Minimized || this.Visibility == Visibility.Hidden)
{
this.Show();
this.WindowState = WindowState.Normal;
}
// According to some sources these steps gurantee that an app will be brought to foreground.
this.Activate();
this.Topmost = true;
this.Topmost = false;
this.Focus();
}
And add Startup="AppOnStartup" (thanks vhanla!):
Works for me :)