使用 Caliburn.Micro 的单实例 WPF 应用程序
Posted
技术标签:
【中文标题】使用 Caliburn.Micro 的单实例 WPF 应用程序【英文标题】:Single instance WPF application using Caliburn.Micro 【发布时间】:2013-12-03 14:42:06 【问题描述】:我已经看到有关使用 WPF 创建单实例应用程序的所有其他问题,并且我选择使用 Microsoft 的方法,如下所述:https://codereview.stackexchange.com/a/25667
这工作正常,但现在我想在这个应用程序上使用 Caliburn.Micro,而这段代码不能很好地与 caliburn 配合使用。
如何使用 caliburn micro 建立单实例 wpf 应用程序?
要求非常简单:.net 4.5 并且每个用户会话只有一个应用程序实例
谢谢
【问题讨论】:
在程序启动时,您可以简单地检查是否有另一个具有相同图像名称的进程正在运行。如果是这样,只需退出应用程序。 @PoweredByOrange 谢谢,但这不是一个非常强大的方法。我目前正在使用互斥锁。问题是如何将这种行为插入 calibur.micro 【参考方案1】:如果有人遇到同样的问题,我想澄清一下步骤。
首先,你必须改变程序入口点发生的事情。正如其他人所提到的,作为 WPF 程序入口点的 Main() 函数是自动生成的 (App.g.i.cs);所以我们必须以某种方式控制它。正如this answer 中提到的,有几种方法可以做到这一点。我个人更喜欢Third Approach:
在您的项目中包含另一个定义 Main 方法的类,如下所示:
class Startup
[STAThread]
public static void Main()
// Your single instance control (shown in below code)
...
确定您希望应用程序将其 main 用作入口点的类。这可以通过项目属性来完成(右键单击您的项目>属性。或在解决方案资源管理器中选择您的项目时按 alt+enter)。在 Application 选项卡中,从下拉列表中修改 Startup 对象属性:
其次,您必须确定一种机制来了解您的程序是否被多次运行。有几种方法可以做到这一点(正如提到的其他答案)。我更喜欢的是这个:
...
// Your single instance control:
bool firstInstance = true;
System.Threading.Mutex mutex = new System.Threading.Mutex(true, "some_unique_name_that_only_your_project_will_use", out firstInstance);
if (firstInstance)
// Everything that needs to be done in main class, for example:
YourProject.App app = new YourProject.App();
app.InitializeComponent();
app.Run();
else
// Your procedure for additional instances of program
MessageBox.Show("Another instance of this application is already running.");
这两个步骤一起是实现目标的最简单方法之一,即使在Caliburn.Micro
控制您的程序之前也是如此。
【讨论】:
【参考方案2】:我在 OnStartup() 方法中尝试此操作时遇到了困难。 基本上,您想创建一个 Main 方法(请参阅 No Main() in WPF? )并使用互斥锁包装内容(请参阅 What is a good pattern for using a Global Mutex in C#?)
我的看起来像这样:
class SingleGlobalInstance : IDisposable
public bool _hasHandle = false;
Mutex _mutex;
private void InitMutex()
string appGuid = "My App Name"; //((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value;
string mutexId = string.Format("Global\\0", appGuid);
_mutex = new Mutex(false, mutexId);
var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
var securitySettings = new MutexSecurity();
securitySettings.AddAccessRule(allowEveryoneRule);
_mutex.SetAccessControl(securitySettings);
public SingleGlobalInstance(int timeOut)
InitMutex();
try
if(timeOut < 0)
_hasHandle = _mutex.WaitOne(Timeout.Infinite, false);
else
_hasHandle = _mutex.WaitOne(timeOut, false);
if (_hasHandle == false)
MessageBox.Show("Another instance is already running");
System.Windows.Application.Current.Shutdown();
catch (AbandonedMutexException)
_hasHandle = true;
public void Dispose()
if (_mutex != null)
if (_hasHandle)
_mutex.ReleaseMutex();
_mutex.Close();
我的 App.xaml.cs 包含:
[STAThread]
public static void Main()
using (new SingleGlobalInstance(1000))
var application = new App();
application.InitializeComponent();
application.Run();
【讨论】:
【参考方案3】:我在我的主要方法中使用named mutex,如果互斥锁已经存在,则显示一个对话框。
检查这个堆栈 - WPF Single Instance Best Practices
【讨论】:
谢谢,但我已经在使用互斥锁了。我的问题是如何将该行为插入 caliburn.micro,因为它使用引导程序来加载应用程序。 在调用引导程序之前执行此操作。见上面的main方法。进程级行为不需要框架。 但是做应用程序初始化逻辑不是有一个引导程序的重点吗? @Adabada Caliburn.Micro 公开了您可以在引导程序中覆盖的OnStartup
方法。
@PatrykĆwiek 那么 onstartup 是这类东西的最佳场所吗?我找不到任何使用 caliburn 的单实例应用程序示例以上是关于使用 Caliburn.Micro 的单实例 WPF 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器