.NET 4 single application instance

前端 未结 4 1873
清歌不尽
清歌不尽 2020-12-03 22:29

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 th

相关标签:
4条回答
  • 2020-12-03 22:35

    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, so you can find the other instance of your app and bring it forward:

    [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.

    0 讨论(0)
  • 2020-12-03 22:38

    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

    0 讨论(0)
  • 2020-12-03 22:40

    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);
    }
    
    0 讨论(0)
  • 2020-12-03 22:51

    There's a simpler way - with help of WindowsFormsApplicationBase class from Microsoft.VisualBasic.ApplicationServices:

    using System;
    using System.Collections.Generic;
    
    public class SingleInstanceApplicationWrapper :
    Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase 
    {
      public SingleInstanceApplicationWrapper()
      {
        IsSingleInstance = true;
      }
    
      private MyApp m_app;
      protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
      {
        // here we create our WPF application
        m_app = new MyApp();
        m_app.Run();
        return false;
      }
    
      protected override void OnStartupNextInstance(Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e)
      {
        m_app.DispatchCommandLineParams(e.CommandLine);
      }
    }
    
    public class MyApp : System.Windows.Application
    {
      protected override void OnStartup(System.Windows.StartupEventArgs e)
      {
        base.OnStartup(e);
        DispatchCommandLineParams(e.Args);
      }
      public void DispatchCommandLineParams(IEnumerable<string> cmdParams)
      {
        // process command line parameters
        Console.WriteLine(this.GetHashCode() + " - dispatched");
      }
    }
    public class Program
    {
      [STAThread]
      public static void Main(string[] args)
      {
        var wrapper = new SingleInstanceApplicationWrapper();
        wrapper.Run(args);
      }
    }
    
    0 讨论(0)
提交回复
热议问题