WPF Application single instance
for WPF if you want to have a single instance (for one session) you can use this code
public class ApplicationSingleInstance : Application
{
protected override void OnStartup(StartupEventArgs e)
{
var currentSessionID = Process.GetCurrentProcess().SessionId;
var currentProcessId = Process.GetCurrentProcess().Id;
var exists = System.Diagnostics.Process.GetProcessesByName(System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location));
var result = exists.Where(p => p.SessionId == currentSessionID && p.Id != currentProcessId)
.OrderBy(p => p.Id)
.ToList();
if (result.Count > 0)
{
#if MESSAGE
string s = "";
int i = 0;
foreach (var item in result)
{
s += "[" + i + "] handle window = " + result[i].MainWindowHandle + " Process ID = " + result[i].Id + "\n";
i++;
}
MessageBox.Show(s);
#endif
UnMinimizeClass.Reactivate(result.First());
Environment.Exit(0);
return;
}
base.OnStartup(e);
}
}
public static class UnMinimizeClass
{
#region Imports
[DllImport("user32.dll")]
static extern bool AllowSetForegroundWindow(int dwProcessId);
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, long uFlags);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll")]
public static extern int EnumWindows(CallBackPtr callPtr, int lPar);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsIconic(IntPtr hWnd);
[DllImport("user32.dll")]
static extern bool IsZoomed(IntPtr hWnd);
public delegate bool CallBackPtr(IntPtr hwnd, int lParam);
#endregion
#region const
private const int SW_RESTORE = 9;
private const int SW_HIDE = 0;
private const int SW_MINIMIZE = 6;
private const int SW_MAXIMIZE = 3;
private const int SW_SHOW = 5;
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
static readonly IntPtr HWND_TOP = new IntPtr(0);
static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
private static class SWP
{
public static readonly int
NOSIZE = 0x0001,
NOMOVE = 0x0002,
NOZORDER = 0x0004,
NOREDRAW = 0x0008,
NOACTIVATE = 0x0010,
DRAWFRAME = 0x0020,
FRAMECHANGED = 0x0020,
SHOWWINDOW = 0x0040,
HIDEWINDOW = 0x0080,
NOCOPYBITS = 0x0100,
NOOWNERZORDER = 0x0200,
NOREPOSITION = 0x0200,
NOSENDCHANGING = 0x0400,
DEFERERASE = 0x2000,
ASYNCWINDOWPOS = 0x4000;
}
#endregion
#region private functions
private static IntPtr GetWindowHandle(uint processId)
{
IntPtr result = IntPtr.Zero;
UnMinimizeClass.EnumWindows((hCurWnd, param) =>
{
uint dwProcessID = 0;
GetWindowThreadProcessId(hCurWnd, out dwProcessID);
if (dwProcessID == processId && IsWindowVisible(hCurWnd))
{
result = hCurWnd;
return false;
}
return true;
}, 0);
return result;
}
private static string GetWindowClassName(IntPtr hWnd)
{
StringBuilder ClassName = new StringBuilder(256);
int nRet = GetClassName(hWnd, ClassName, ClassName.Capacity);
return nRet != 0 ? ClassName.ToString() : null;
}
private static string GetWindowTitle(IntPtr hWnd)
{
// Allocate correct string length first
int length = GetWindowTextLength(hWnd);
StringBuilder sb = new StringBuilder(length + 1);
GetWindowText(hWnd, sb, sb.Capacity);
return sb.ToString();
}
private static int GetWindowStat(IntPtr hWnd)
{
if (!IsWindowVisible(hWnd))
return SW_HIDE;
else if (IsIconic(hWnd))
return SW_MINIMIZE;
else if (IsZoomed(hWnd))
return SW_MAXIMIZE;
else
return SW_SHOW;
}
#endregion
#region public Reactivate
public static void Reactivate(Process process)
{
IntPtr handle = process.MainWindowHandle;
if (process.MainWindowHandle.ToInt32() == 0)
{
handle = GetWindowHandle((uint)process.Id);
#if MESSAGE
MessageBox.Show("pointeur a zero = " + handle + " window handle = " + FindWindow(null, "XXX"));
#endif
}
Reactivate(handle, process.Id);
}
public static void Reactivate(IntPtr handle, int processId)
{
int stat = GetWindowStat(handle);
if (stat == SW_MAXIMIZE)
{
SetForegroundWindow(handle);
SetWindowPos(handle, (IntPtr)HWND_TOP, 0, 0, 0, 0, SWP.NOMOVE | SWP.NOSIZE | SWP.SHOWWINDOW);
}
else if (stat == SW_HIDE)
{
ShowWindow(handle, SW_SHOW);
SetForegroundWindow(handle);
SetWindowPos(handle, (IntPtr)HWND_TOP, 0, 0, 0, 0, SWP.NOMOVE | SWP.NOSIZE | SWP.SHOWWINDOW);
}
else
{
ShowWindow(handle, (int)SW_RESTORE);
SetForegroundWindow(handle);
SetWindowPos(handle, (IntPtr)HWND_TOP, 0, 0, 0, 0, SWP.NOMOVE | SWP.NOSIZE | SWP.SHOWWINDOW);
}
}
#endregion
}
and hinerite your App class from ApplicationSingleInstance
don’t forget to change in App Xaml like this
<local:ApplicationSingleInstance x:Class="XX.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:XX"
...
if your namespace is XX
