【问题标题】:Single instance WPF application using Caliburn.Micro使用 Caliburn.Micro 的单实例 WPF 应用程序
【发布时间】: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

标签: c# wpf caliburn.micro single-instance


【解决方案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 的单实例应用程序示例
      猜你喜欢
      • 2015-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多