如何创建在尝试打开另一个实例时恢复打开的窗口的单实例 WPF 应用程序?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21789899/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create single instance WPF Application that restores the open window when an attempt is made to open another instance?
提问by Tsukasa
Sorry it the title is hard to understand. I wasn't sure how to word it.
对不起,标题很难理解。我不知道怎么说。
I have an application that should only be allowed to run one instance per user session. If the user clicks to launch the application again, I want to bring the one already to focus.
我有一个应用程序,应该只允许每个用户会话运行一个实例。如果用户再次单击以启动该应用程序,我想将已聚焦的应用程序聚焦。
The window will likely have Visibility to collapsed.
窗口可能会折叠起来。
If it's visible I know I can use
如果它是可见的,我知道我可以使用
if (IsIconic(hWnd))
{
ShowWindowAsync(hWnd, swRestore);
}
SetForegroundWindow(hWnd);
but if the window is collapsed, is there a way for me to bring it back to visible?
但是如果窗户倒塌了,有没有办法让它恢复可见?
回答by Sheridan
You're looking for the MutexClass. It's pretty complicated, but luckily the Singleton Pattern has been widely discussed. There are several good articles on it, but you can find a good implementation of it in the C# .NET Single Instance Applicationpage on the Sanity Free Coding website. From the linked page:
您正在寻找MutexClass。它相当复杂,但幸运的是,单例模式已被广泛讨论。有几篇关于它的好文章,但您可以在 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");
}
}
}
Now you're probably wondering how to have a Mainmethod in a WPF Application, right? Well there's a few things that you have to do, but it's not difficult. See the Writing a custom Main() method for WPF applicationsarticle which explains this in detail. From that article:
现在您可能想知道如何Main在 WPF 应用程序中使用方法,对吗?好吧,您必须做一些事情,但这并不困难。请参阅为 WPF 应用程序编写自定义 Main() 方法一文,详细解释了这一点。从那篇文章:
You basically need to change the application's build action from “Application Definition” to “Page”, create a constructor that calls “InitializeComponent”, and write your Main() by eventually calling one of the application's “Run” method overloads. ... Don't forget, also, to remove the “StartupUri” from the App.xaml, otherwise another copy of window will show up (unless you get an error because the URI points to a non existing XAML resource).
您基本上需要将应用程序的构建操作从“应用程序定义”更改为“页面”,创建一个调用“InitializeComponent”的构造函数,并通过最终调用应用程序的“Run”方法重载之一来编写 Main()。...也不要忘记从 App.xaml 中删除“StartupUri”,否则将显示另一个窗口副本(除非由于 URI 指向不存在的 XAML 资源而出现错误)。
So by amalgamating these two resources, we can see that your App.xaml.csfile should look something like this:
因此,通过合并这两个资源,我们可以看到您的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;
}
}
}
回答by Ricardo Fran?a
I removed the tag StartupUrifrom the App.xaml file.
我StartupUri从 App.xaml 文件中删除了标记。
Change the Build Action of App.xaml, from ApplicationDefinitionto Page(You can change it on the property window).
将 App.xaml 的 Build Action 从更改ApplicationDefinition为Page(您可以在属性窗口中更改)。
Add a reference to Microsoft.VisualBasic(namespace to WindowsFormsApplicationBase).
添加对Microsoft.VisualBasic(WindowsFormsApplicationBase 的命名空间)的引用。
On the class App.xaml.cs, put this code:
在类上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();
}
}
I hope it helps :D
我希望它有帮助:D

