c# - What is the correct way to create a single-instance application? -
using c# , wpf under .net (rather windows forms or console), correct way create application can run single instance?
i know has mythical thing called mutex, can find bothers stop , explain 1 of these are.
the code needs inform already-running instance user tried start second one, , maybe pass command-line arguments if existed.
here article regarding mutex solution. approach described article advantageous 2 reasons.
first, not require dependency on microsoft.visualbasic assembly. if project had dependency on assembly, advocate using approach shown in accepted answer. is, not use microsoft.visualbasic assembly, , i'd rather not add unnecessary dependency project.
second, article shows how bring existing instance of application foreground when user tries start instance. that's nice touch other mutex solutions described here not address.
update
as of 8/1/2014, article linked above still active, blog hasn't been updated in while. makes me worry might disappear, , it, advocated solution. i'm reproducing content of article here posterity. words belong solely blog owner @ sanity free coding.
today wanted refactor code prohibited application running multiple instances of itself.
previously had use system.diagnostics.process search instance of myapp.exe in process list. while works, brings on lot of overhead, , wanted cleaner.
knowing use mutex (but never having done before) set out cut down code , simplify life.
in class of application main created static named mutex:
static class program { static mutex mutex = new mutex(true, "{8f6f0ac4-b9a1-45fd-a8cf-72f04e6bde8f}"); [stathread] ... }
having named mutex allows stack synchronization across multiple threads , processes magic i'm looking for.
mutex.waitone has overload specifies amount of time wait. since we're not wanting synchronizing our code (more check if in use) use overload 2 parameters: mutex.waitone(timespan timeout, bool exitcontext). wait 1 returns true if able enter, , false if wasn't. in case, don't want wait @ all; if our mutex being used, skip it, , move on, pass in timespan.zero (wait 0 milliseconds), , set exitcontext true can exit synchronization context before try aquire lock on it. using this, wrap our application.run code inside 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 1 instance @ time"); } } }
so, if our app running, waitone return false, , we'll message box.
instead of showing message box, opted utilize little win32 notify running instance forgot running (by bringing top of other windows). achieve used postmessage broadcast custom message every window (the custom message registered registerwindowmessage running application, means application knows is) second instance exits. running application instance receive notification , process it. in order that, overrode wndproc in main form , listened custom notification. when received notification set form's topmost property true bring on top.
here ended with:
- program.cs
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 make running instance // jump on top of other windows nativemethods.postmessage( (intptr)nativemethods.hwnd_broadcast, nativemethods.wm_showme, intptr.zero, intptr.zero); } } }
- nativemethods.cs
// class wraps win32 stuff we're going 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; } // our current "topmost" value (ours false though) bool top = topmost; // make our form jump top of topmost = true; // set whatever topmost = top; } }
Comments
Post a Comment