Here is a very good article regarding the Mutex solution. The approach described by the article is advantageous for two reasons.
First, it does not require a dependency on the Microsoft.VisualBasic assembly. If my project already had a dependency on that assembly, I would probably advocate using the approach shown in another answer. But as it is, I do not use the Microsoft.VisualBasic assembly, and I'd rather not add an unnecessary dependency to my project.
Second, the article shows how to bring the existing instance of the application to the foreground when the user tries to start another instance. That's a very nice touch that the other Mutex solutions described here do not address.
UPDATE
As of 8/1/2014, the article I linked to above is still active, but the blog hasn't been updated in a while. That makes me worry that eventually it might disappear, and with it, the advocated solution. I'm reproducing the content of the article here for posterity. The words belong solely to the blog owner at Sanity Free Coding.
Today I wanted to refactor some code that prohibited my application
from running multiple instances of itself.
Previously I had use System.Diagnostics.Process to search for an
instance of my myapp.exe in the process list. While this works, it
brings on a lot of overhead, and I wanted something cleaner.
Knowing that I could use a mutex for this (but never having done it
before) I set out to cut down my code and simplify my life.
In the class of my application main I created a static named Mutex:
static class Program
{
static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
[STAThread]
...
}
Having a named mutex allows us to stack synchronization across
multiple threads and processes which is just the magic I'm looking
for.
Mutex.WaitOne has an overload that specifies an amount of time for us
to wait. Since we're not actually wanting to synchronizing our code
(more just check if it is currently in use) we use the overload with
two parameters: Mutex.WaitOne(Timespan timeout, bool exitContext).
Wait one returns true if it is able to enter, and false if it wasn't.
In this case, we don't want to wait at all; If our mutex is being
used, skip it, and move on, so we pass in TimeSpan.Zero (wait 0
milliseconds), and set the exitContext to true so we can exit the
synchronization context before we try to aquire a lock on it. Using
this, we wrap our Application.Run code inside something like this:
static class Program
{
static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
[STAThread]
static void Main() {
if(mutex.WaitOne(TimeSpan.Zero, true)) {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
mutex.ReleaseMutex();
} else {
MessageBox.Show("only one instance at a time");
}
}
}
So, if our app is running, WaitOne will return false, and we'll get a
message box.
Instead of showing a message box, I opted to utilize a little Win32 to
notify my running instance that someone forgot that it was already
running (by bringing itself to the top of all the other windows). To
achieve this I used PostMessage to broadcast a custom message to every
window (the custom message was registered with RegisterWindowMessage
by my running application, which means only my application knows what
it is) then my second instance exits. The running application instance
would receive that notification and process it. In order to do that, I
overrode WndProc in my main form and listened for my custom
notification. When I received that notification I set the form's
TopMost property to true to bring it up on top.
Here is what I ended up with:
static class Program
{
static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
[STAThread]
static void Main() {
if(mutex.WaitOne(TimeSpan.Zero, true)) {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
mutex.ReleaseMutex();
} else {
// send our Win32 message to make the currently running instance
// jump on top of all the other windows
NativeMethods.PostMessage(
(IntPtr)NativeMethods.HWND_BROADCAST,
NativeMethods.WM_SHOWME,
IntPtr.Zero,
IntPtr.Zero);
}
}
}
// this class just wraps some Win32 stuff that we're going to use
internal class NativeMethods
{
public const int HWND_BROADCAST = 0xffff;
public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");
[DllImport("user32")]
public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
[DllImport("user32")]
public static extern int RegisterWindowMessage(string message);
}
- Form1.cs (front side partial)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
if(m.Msg == NativeMethods.WM_SHOWME) {
ShowMe();
}
base.WndProc(ref m);
}
private void ShowMe()
{
if(WindowState == FormWindowState.Minimized) {
WindowState = FormWindowState.Normal;
}
// get our current "TopMost" value (ours will always be false though)
bool top = TopMost;
// make our form jump to the top of everything
TopMost = true;
// set it back to whatever it was
TopMost = top;
}
}
If you want to bind to another property on the object:
{Binding Path=PathToProperty, RelativeSource={RelativeSource Self}}
If you want to get a property on an ancestor:
{Binding Path=PathToProperty,
RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}}
If you want to get a property on the templated parent (so you can do 2 way bindings in a ControlTemplate)
{Binding Path=PathToProperty, RelativeSource={RelativeSource TemplatedParent}}
or, shorter (this only works for OneWay bindings):
{TemplateBinding Path=PathToProperty}
Best Answer
OK, your app sounds large! I can share my experiences around an application we engineered recently; it was a GUI talking web services to a server that in turn contacted multiple databases and other web services. The client base was around 15,000 users… Either way - this is a lot of work no matter how you approach it; the upside is it will help you not chew your nails off each time you make a release!
MVVM
In general I would also recommend the MVVM pattern and do as much testing as possible without the GUI. GUI testing is just plain hard! I like Josh Smith’s article on MSDN: "WPF Apps With The Model-View-ViewModel Design Pattern" (http://msdn.microsoft.com/en-us/magazine/dd419663.aspx)
Test Scripting
The trick with this app was that we had a lot to test, the guts of it were constantly moving and there were (strangely enough) not enough people to get the testing job done for each iteration.
My solution was to come up with a custom testing tool that leveraged existing libraries. We had a simple script engine that read a file and executed commands. In effect we developed a DSL (http://en.wikipedia.org/wiki/Domain-specific_language) for testing our specific application. The DSL included some simple commands to signal what "window" it was testing, any specific "setup" signals and then a series of commands followed by assertions. It looked something like this:
The format of each line is
The scripts go into groups of directories and the "test runner" loads them up, parses them and executes them. Creating logs and reports as you go is useful, I got added in hook for making screen-shots etc which came in handy. If you are interested in implementing something likke this and would like a hand let me know.
The handy thing here was that we could make blanket changes to the test strategy.
Writing the scripts becomes pretty simple which is important because you end up with many, many scripts. The controls are discovered by name so you follow a convention (e.g. “Name” may be "NameTextBox" in code, or “Save” could be "SaveButton").
You can actually harness NUnit etc to be your test runner too.
NOTE - Just run the tests interactively, getting GUI test to work with CI is difficult and problematic...
Data and Testing
One major thing here is that the data management was a huge part of the test problem and cannot be overlooked. Our “fresh deployment” was also very long but some parts were external and we had no control over the freshness of the data. The way we handled the cleaning was to provide hooks through the scripting that allowed us to easily remove objects before tests. Not optimal but was rarely an issue.
Libraries
The library that you may find most useful in "White" (http://white.codeplex.com/) It can test windows apps in general – i.e both WPF and WinForms. Essentially you end up coding things like this:
If your app makes async calls you will need to come up with a strategy for the test runner to know when the async call is finished, perhaps though the status bar or something. It depend how you hook in…
Again, a lot of work but it’s worth it.
PK :-)