tags:

views:

171

answers:

5

I often write .net applications that only support one instance. Formerly I used .net-remoting and now WCF to detect if already an instance of my app is running and giving the focus to this instance.

My question is, if there is with .net4 a better solution available to achieve single instance applications (or is there in general a better solution available, because loading the WCF or remoting assembly at the very start of the application has a bad performance influence)

Update

Thanks for all the post. The answer to my initial question seems to be “no, there is nothing new to achieve single instance applications within .net 4”.

Thanks to all the additional information, I will change my current projects to use a Mutex to provide the desired functionality. I accepted the answer of Bob Moore because it has the most information attached to it, but thanks to all who posted useful information.

+1  A: 

This looks pretty elegant as well: Single instance Application

weismat
+6  A: 

The traditional way to do this is with a mutex, e.g.

bool bNew = true; 
using (Mutex mutex = new Mutex(true, "MYAPP_0D36E4C9-399D-4b05-BDA3-EE059FB77E8D", out bNew))
{
   if (bNew)
   {
       // blah, blah,
       Application.Run(new MainForm());
   }
}

Edit:

I found this code to invoke SetForegroundWindow online:

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);


Process me = Process.GetCurrentProcess();
foreach (Process process in Process.GetProcessesByName (me.ProcessName))
{
   if (process.Id != me.Id)
   {
      SetForegroundWindow (process.MainWindowHandle);
      break;
   }
}

Note that in modern Windows implementations you can only give the foreground away.

Bob Moore
Does this work also in Terminal-Server environments?
HCL
A Mutex can be per session or machine wide.
GvS
And how to activate the existing Application (Give Focus)? PInvoke?
HCL
I believe each terminal server session has a private namespace for kernel objects. I suggest you read www.flounder.com/nomultiples.htm for a more comprehensive background. That's a native code site, but you need to understand the principles if you're venturing this far down into the innards...
Bob Moore
I see others have pointed you at the global/local flags. Of course, it depends on what you mean by "work for terminal server". You can set it up to only allow one instance on a single physical machine, or on a single terminal.
Bob Moore
btw, it's rather better to extract `[assembly: Guid]` value than hardcode someone
abatishchev
+2  A: 

I use a Mutex, and FindWindow to do this.

Concerning your comment on another answer:
For information on Local and Global mutexes in Terminal Services, follow this link.

Terminal Services client processes can use object names with a "Global\" or "Local\" prefix to explicitly create an object in the global or session name space.

This is the code I use to activate the window:

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsIconic(IntPtr hWnd);

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
private const int SH_SHOW = 5;
private const int SH_RESTORE = 9;

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);

public void Activate(IntPtr hwnd)
{
    if (IsIconic(hwnd))
        ShowWindow(hwnd, SH_RESTORE);
    else
        ShowWindow(hwnd, SH_SHOW);

    SetForegroundWindow(hwnd);
}
GvS
A: 

I would suggest Singleton-Pattern. Look at this (example for VB.net!):http://vbnotebookfor.net/2007/09/13/introduction-to-the-singleton-pattern-in-vbnet/

Greetz

Husky110
Sorry, I dont't understand how it helps? The singleton pattern works in the applications domain but not over different processes.
HCL
-1 That only works within a process, indeed.
Jouke van der Maas