Wednesday, June 30, 2010

Making your WPF application single instance

I used the ideas in this article. However, when bringing my
application to the top, I used my own methods. Below is the link to
the article, and the code that I used.
http://sanity-free.org/143/csharp_dotnet_single_instance_application.html

However, I used the following:
In my Startup.cs file I did the following:

static Mutex mutex = new Mutex(true,
"{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
[STAThread]
public static void Main()
{
try
{
if (mutex.WaitOne(TimeSpan.Zero, true))
{
MyApp app = new MyApp
app.InitializeComponent();
app.Run();
mutex.ReleaseMutex();
}
else
{
// send our Win32 message to make the currently
running instance
// jump on top of all the other windows
NativeMethods.BringTMForeGround();
}
}
catch (Exception e)
{//Catch all un-handle exception from the application

}
}

And in my NativeMethods.cs I did the following:
[DllImport("User32", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(string lpClassName, string
lpWindowName);

[DllImport("User32", EntryPoint = "BringWindowToTop")]
public static extern bool BringWindowToTop(IntPtr wHandle);

[DllImport("User32", EntryPoint = "SetForegroundWindow")]
public static extern bool SetForegroundWindow(IntPtr wHandle);

[DllImport("User32", EntryPoint = "SetFocus")]
public static extern bool SetFocus(IntPtr wHandle);

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

public static void BringTMForeGround()
{
try
{
bool ret = false;
IntPtr hWnd = NativeMethods.FindWindow(null, "Title of
Application Window"); // Get Window of App2

if (hWnd == IntPtr.Zero)
{
FindWindowLike.Window[] list = FindWindowLike.Find(0, "Title
of Application Window", "");
if (list.Length >= 1)
hWnd = (IntPtr)list[0].Handle;
}
if (hWnd != IntPtr.Zero) // Check if App2 exists
{
ret = NativeMethods.SetForegroundWindow(hWnd);
ret = NativeMethods.ShowWindow(hWnd, 9);
ret = NativeMethods.BringWindowToTop(hWnd);
//ret = SetFocus(hWnd);
}
}
catch (Exception)
{
}
}


The function FindWinowLike was another class and this is whats in it:
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;

namespace MyAppNamespace
{
public class FindWindowLike
{

public class Window
{
public string Title;
public string Class;
public int Handle;
}

[DllImport("user32")]
private static extern int GetWindow(int hwnd, int wCmd);

[DllImport("user32")]
private static extern int GetDesktopWindow();

[DllImport("user32", EntryPoint = "GetWindowLongA")]
private static extern int GetWindowLong(int hwnd, int nIndex);

[DllImport("user32")]
private static extern int GetParent(int hwnd);

[DllImport("user32", EntryPoint = "GetClassNameA")]
private static extern int GetClassName(
int hWnd, [Out] StringBuilder lpClassName, int nMaxCount);

[DllImport("user32", EntryPoint = "GetWindowTextA")]
private static extern int GetWindowText(
int hWnd, [Out] StringBuilder lpString, int nMaxCount);

private const int GWL_ID = (-12);
private const int GW_HWNDNEXT = 2;
private const int GW_CHILD = 5;

public static Window[] Find(int hwndStart, string findText, string
findClassName)
{

ArrayList windows = DoSearch(hwndStart, findText, findClassName);

return (Window[])windows.ToArray(typeof(Window));

} //Find


private static ArrayList DoSearch(int hwndStart, string findText,
string findClassName)
{

ArrayList list = new ArrayList();

if (hwndStart == 0)
hwndStart = GetDesktopWindow();

int hwnd = GetWindow(hwndStart, GW_CHILD);

while (hwnd != 0)
{

// Recursively search for child windows.
list.AddRange(DoSearch(hwnd, findText, findClassName));

StringBuilder text = new StringBuilder(255);
int rtn = GetWindowText(hwnd, text, 255);
string windowText = text.ToString();
windowText = windowText.Substring(0, rtn);

StringBuilder cls = new StringBuilder(255);
rtn = GetClassName(hwnd, cls, 255);
string className = cls.ToString();
className = className.Substring(0, rtn);

if (GetParent(hwnd) != 0)
rtn = GetWindowLong(hwnd, GWL_ID);

if (windowText.Length > 0 && windowText.StartsWith(findText) &&
(className.Length == 0 || className.StartsWith(findClassName)))
{
Window currentWindow = new Window();

currentWindow.Title = windowText;
currentWindow.Class = className;
currentWindow.Handle = hwnd;

list.Add(currentWindow);
}

hwnd = GetWindow(hwnd, GW_HWNDNEXT);

}

return list;

} //DoSearch

} //Class

}

No comments: