我经常编写仅支持一个实例的.net应用程序。以前我使用.net-remoting和现在的WCF来检测我的应用程序的实例是否正在运行并将焦点放在此实例上。
我的问题是,如果.net4有更好的解决方案可用于实现单实例应用程序(或者通常有更好的解决方案可用,因为在应用程序一开始就加载WCF或远程处理程序集有坏处绩效影响)
更新
感谢所有帖子。我最初的问题的答案似乎是“不,在.net 4 中实现单实例应用程序没有什么新东西”。
感谢所有附加信息,我将更改当前项目以使用Mutex提供所需的功能。我接受了Bob Moore的答案,因为它附带了最多的信息,但感谢所有发布有用信息的人。
答案 0 :(得分:11)
传统的方法是使用互斥锁,例如
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实现中,您只能放弃前景。
答案 1 :(得分:2)
我使用Mutex和FindWindow来执行此操作。
关于您对其他答案的评论:
有关终端服务中本地和全局互斥锁的信息,follow this link。
终端服务客户端进程 可以使用带有“全局”的对象名称 或显式的“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);
}
答案 2 :(得分:2)
有一种更简单的方法 - 借助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);
}
}
答案 3 :(得分:-2)
我建议使用Singleton-Pattern。 看看这个(VB.net的例子!):http://vbnotebookfor.net/2007/09/13/introduction-to-the-singleton-pattern-in-vbnet/
格尔茨