繁体   English   中英

使用 Caliburn.Micro 的单实例 WPF 应用程序

[英]Single instance WPF application using Caliburn.Micro

我已经看到了有关使用 WPF 创建单实例应用程序的所有其他问题,并且我选择使用 Microsoft 的方法,如下所述: https : //codereview.stackexchange.com/a/25667

这工作正常,但现在我想在此应用程序上使用 Caliburn.Micro 并且此代码与 caliburn 不兼容。

如何使用 caliburn micro 拥有单实例 wpf 应用程序?

要求非常简单:.net 4.5 并且每个用户会话只有一个应用程序实例

谢谢

我在我的主要方法中使用了一个命名的互斥锁,如果互斥锁已经存在,则显示一个对话框。

检查此堆栈 - WPF 单实例最佳实践

如果有人遇到同样的问题,我想澄清这些步骤。

首先,您必须更改程序入口点中发生的事情。 正如其他人提到的,作为 WPF 程序入口点的 Main() 函数是自动生成的 ( App.gics ); 所以我们必须以某种方式控制它。 正如在这个答案中提到的,有几种方法可以做到这一点。 我个人更喜欢第三种方法

在您的项目中包含另一个定义 Main 方法的类,如下所示:

class Startup
{
    [STAThread]
    public static void Main()
    {
        // Your single instance control (shown in below code)
        ...
    }
}

确定您希望应用程序将其 main 用作入口点的类。 这可以通过项目属性来完成(在解决方案资源管理器中选择您的项目时,右键单击您的项目 > 属性。或 alt+enter)。 在应用程序选项卡中,从下拉列表中修改启动对象属性:

其次,您必须决定一种机制来了解您的程序是否被多次运行。 有几种方法可以做到这一点(如提到的其他答案)。 我更喜欢的是这个:

        ...
        // 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控制您的程序之前。

我在 OnStartup() 方法中尝试这个有困难。 基本上,您想创建一个 Main 方法(请参阅WPF 中的 No Main()? )并使用互斥锁包装内容(请参阅在 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();
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM