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

时间:2013-11-19 20:55:34

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

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

这很好用,但现在我想在这个应用程序上使用Caliburn.Micro,这段代码与caliburn不兼容。

如何使用caliburn micro创建单个实例wpf应用程序?

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

由于

3 个答案:

答案 0 :(得分:3)

我在main方法中使用named mutex,如果互斥锁已经存在,则会显示一个对话框。

检查此堆栈 - WPF Single Instance Best Practices

答案 1 :(得分:2)

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

首先,您必须更改程序入口点发生的情况。如其他提到的那样,用作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)
        ...
    }
}

标识您要应用程序用作入口点的主类。这可以通过项目属性来完成(在“解决方案资源管理器”中选择了项目时,右键单击项目> properties。在“应用程序”选项卡中,从下拉菜单中修改“启动对象”属性:

第二,,您必须确定一种机制来知道您的程序是否正在运行多次。有几种方法可以做到这一点(以及其他提到的答案)。我更喜欢的是这样:

        ...
        // 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 :(得分:0)

我很难在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\\{Debug result}", 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();
        }
    }