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

5
我看到了所有关于使用WPF创建单个实例应用程序的其他问题,我选择使用Microsoft的方法,如此处所述:https://codereview.stackexchange.com/a/25667 这个方法很好用,但现在我想在这个应用程序上使用Caliburn.Micro,而这段代码与caliburn不兼容。
如何使用Caliburn Micro创建一个单实例wpf应用程序?
需求非常简单:.net 4.5和每个用户会话仅一个应用程序实例
谢谢

在程序启动时,您可以简单地检查是否有另一个具有相同图像名称的进程正在运行。如果是,则只需退出应用程序。 - Arian Motamedi
1
@PoweredByOrange 谢谢,但那不是一个非常健壮的方法。我目前正在使用互斥锁。问题是如何将该行为插入到calibur.micro中。 - Adabada
3个回答

5

谢谢,但我已经在使用互斥锁了。我的问题是如何将这种行为插入到 Caliburn.Micro 中,因为它使用引导程序来加载应用程序。 - Adabada
在调用引导程序之前执行此操作。请参见上面的_main方法。进程级别的行为不需要框架。 - Gusdor
但是,难道不是通过引导程序来执行应用初始化逻辑的吗? - Adabada
@Adabada Caliburn.Micro公开了OnStartup方法,您可以在引导程序中重写它。 - Patryk Ćwiek
@PatrykĆwiek 那么onstartup是这种类型的最佳位置吗?我找不到使用caliburn的单个实例应用程序的任何示例。 - Adabada
@Adabada 试一下,看看是否可行,如果可行就行!单个实例的目标是防止共享资源和相关副作用的竞争。只要你能在任何东西初始化之前关闭应用程序,那就 bingo! - Gusdor

3

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

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

在您的项目中包含另一个类,该类将Main方法定义为以下内容:

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

确定你希望应用程序使用哪个类作为入口点。可以通过项目属性(右键单击项目->属性或在解决方案资源管理器中选择项目时按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 接管您的程序之前也可以使用。


0

我在OnStartup()方法中尝试这个时遇到了困难。 基本上,您需要创建一个Main方法(参见WPF中没有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();
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接