【问题标题】:.NET 4 single application instance.NET 4 单个应用程序实例
【发布时间】:2010-07-09 09:53:54
【问题描述】:

我经常编写仅支持一个实例的 .net 应用程序。以前我使用 .net-remoting 和现在的 WCF 来检测我的应用程序的一个实例是否已经在运行并将焦点放在这个实例上。

我的问题是,如果 .net4 有更好的解决方案来实现单实例应用程序(或者一般来说有更好的解决方案,因为在应用程序的一开始就加载 WCF 或远程程序集有一个不好的性能影响)

更新

感谢所有的帖子。我最初的问题的答案似乎是“不,在 .net 4 中实现单实例应用程序没有什么新东西”。

感谢所有其他信息,我将更改我当前的项目以使用 Mutex 来提供所需的功能。我接受了 Bob Moore 的回答,因为它附带的信息最多,但感谢所有发布有用信息的人。

【问题讨论】:

  • .net 4 没什么特别的。wcf 和远程处理听起来像这样简单的任务的巨大开销
  • @Andrey:确实,它的开销,但我不得不说,在大多数这些应用程序中,我无论如何都使用 WCF/Remoting,这证明了它们的使用是合理的。但是加载程序集的时间点很糟糕,因为它延长了应用程序加载/初始化的时间。
  • 您应该使用互斥锁,正如 Bob Moore 的回答中所述。它健壮且快速。
  • @Andrey 所以我会的。谢谢。

标签: .net


【解决方案1】:

执行此操作的传统方法是使用互斥体,例如

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());
   }
}

编辑:

我在网上找到了这个调用 SetForegroundWindow 的代码,这样你就可以找到你的应用程序的另一个实例并将其提交:

[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;
   }
}

请注意,在现代 Windows 实现中,您只能放弃前景。

【讨论】:

  • 互斥锁可以在每个会话或机器范围内。
  • 以及如何激活现有的应用程序(Give Focus)? PInvoke?
  • 我相信每个终端服务器会话都有一个用于内核对象的私有命名空间。我建议您阅读 www.flounder.com/nomultiples.htm 以获得更全面的背景信息。那是一个本地代码站点,但如果您要深入了解内部代码,则需要了解这些原则...
  • 我看到其他人已将您指向全局/本地标志。当然,这取决于您所说的“为终端服务器工作”是什么意思。您可以将其设置为仅允许单个物理机或单个终端上的一个实例。
  • 顺便说一句,提取[assembly: Guid] 值比硬编码某人更好
【解决方案2】:

我使用Mutex 和FindWindow 来执行此操作。

关于您对另一个答案的评论:
有关终端服务中的本地和全局互斥锁的信息,follow this link。

终端服务客户端进程 可以使用带有“Global\”的对象名称 或“Local\”前缀显式 在全局中创建一个对象或 会话名称空间。

这是我用来激活窗口的代码:

[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);
}

【讨论】:

    【解决方案3】:

    有一种更简单的方法 - 借助 Microsoft.VisualBasic.ApplicationServices 中的 WindowsFormsApplicationBase 类:

    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);
      }
    }
    

    【讨论】:

      【解决方案4】:

      我建议使用单例模式。 看看这个(VB.net的例子!):http://vbnotebookfor.net/2007/09/13/introduction-to-the-singleton-pattern-in-vbnet/

      问候

      【讨论】:

      • 抱歉,我不明白它有什么帮助?单例模式适用于应用程序域,但不适用于不同的进程。
      猜你喜欢
      • 2018-04-10
      • 1970-01-01
      • 2012-12-02
      • 2020-04-29
      • 1970-01-01
      • 1970-01-01
      • 2017-04-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多