如何创建单实例 WPF 应用程序以在尝试打开另一个实例时恢复打开的窗口? [复制]
Posted
技术标签:
【中文标题】如何创建单实例 WPF 应用程序以在尝试打开另一个实例时恢复打开的窗口? [复制]【英文标题】:How to create single instance WPF Application that restores the open window when an attempt is made to open another instance? [duplicate] 【发布时间】:2014-02-14 21:34:10 【问题描述】:对不起,标题很难理解。我不知道该怎么说。
我有一个应用程序,应该只允许每个用户会话运行一个实例。 如果用户再次单击以启动应用程序,我想将已经聚焦的那个。
该窗口可能具有折叠的可见性。
如果它是可见的,我知道我可以使用
if (IsIconic(hWnd))
ShowWindowAsync(hWnd, swRestore);
SetForegroundWindow(hWnd);
但是如果窗口被折叠,我有办法让它恢复可见吗?
【问题讨论】:
【参考方案1】:您正在寻找Mutex
Class。这相当复杂,但幸运的是单例模式已被广泛讨论。有几篇关于它的好文章,但你可以在 Sanity Free Coding 网站上的 C# .NET Single Instance Application 页面中找到它的一个很好的实现。从链接页面:
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 one instance at a time");
现在您可能想知道如何在 WPF 应用程序中使用 Main
方法,对吧?好吧,您必须做一些事情,但这并不难。请参阅Writing a custom Main() method for WPF applications 文章,其中详细解释了这一点。从那篇文章:
您基本上需要将应用程序的构建操作从“应用程序定义”更改为“页面”,创建一个调用“InitializeComponent”的构造函数,并通过最终调用应用程序的“运行”方法重载之一来编写您的 Main()。 ...不要忘记从 App.xaml 中删除“StartupUri”,否则将显示另一个窗口副本(除非您收到错误,因为 URI 指向不存在的 XAML 资源)。
因此,通过合并这两个资源,我们可以看到您的 App.xaml.cs
文件应如下所示:
public partial class App : Application
private static Mutex mutex = new Mutex(true, "8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F");
private static MainWindow mainWindow = null;
App()
InitializeComponent();
[STAThread]
static void Main()
if(mutex.WaitOne(TimeSpan.Zero, true))
App app = new App();
mainWindow = new MainWindow();
app.Run(mainWindow);
mutex.ReleaseMutex();
else
mainWindow.WindowState = WindowState.Normal;
【讨论】:
在我看来,上面放弃了第一个应用程序实例中的互斥锁。来自文档:“拥有互斥锁的线程可以在重复调用 WaitOne 时请求相同的互斥锁,而不会阻止其执行。但是,线程必须调用 ReleaseMutex 方法相同的次数才能释放互斥锁的所有权” 。创建互斥锁时,如果您是第一个实例,则互斥锁已经获得;然后您通过调用WaitOne()
再次获取它。如果要获得两次,则需要释放两次。【参考方案2】:
我从 App.xaml 文件中删除了标签 StartupUri
。
将 App.xaml 的 Build Action 由 ApplicationDefinition
更改为 Page
(您可以在属性窗口中更改)。
添加对Microsoft.VisualBasic
的引用(WindowsFormsApplicationBase 的命名空间)。
在App.xaml.cs
类上,输入以下代码:
public partial class App : Application
App()
InitializeComponent();
[STAThread]
static void Main()
SingleInstanceManager manager = new SingleInstanceManager();
manager.Run(new[] "teste");
public class SingleInstanceManager : WindowsFormsApplicationBase
SingleInstanceApplication app;
public SingleInstanceManager()
this.IsSingleInstance = true;
protected override bool OnStartup(Microsoft.VisualBasic.ApplicationServices.StartupEventArgs e)
// First time app is launched
app = new SingleInstanceApplication();
app.Run();
return false;
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
// Subsequent launches
base.OnStartupNextInstance(eventArgs);
app.Activate();
public class SingleInstanceApplication : Application
protected override void OnStartup(System.Windows.StartupEventArgs e)
base.OnStartup(e);
// Create and show the application's main window
MainWindow window = new MainWindow();
window.Show();
public void Activate()
// Reactivate application's main window
this.MainWindow.WindowState = WindowState.Normal;
this.MainWindow.Activate();
【讨论】:
以上是关于如何创建单实例 WPF 应用程序以在尝试打开另一个实例时恢复打开的窗口? [复制]的主要内容,如果未能解决你的问题,请参考以下文章