使用 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 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

使用 Caliburn.Micro 附加到多个事件

从0到1:使用Caliburn.Micro(WPF和MVVM)开发简单的计算器

Caliburn.Micro框架之Bindings

使用 WPF 和 Caliburn.Micro 在视图中添加多个视图

MVVM框架 -- Caliburn.Micro 系列文章

Caliburn.Micro 能否很好地与用户控件配合使用?