【问题标题】:WPF, how to make a single instance and shows the MainWindow when another instance is launched in c#WPF,如何制作单个实例并在c#中启动另一个实例时显示MainWindow
【发布时间】:2013-07-21 12:36:55
【问题描述】:

作为标题状态,我想制作一个单实例程序并在启动另一个实例时显示 MainWindow。 我已经实现了显示只允许一个实例的消息。

public class MyApplication
{
static Mutex mutex = new Mutex(true, "FirstInstance");
    [STAThread]
    public static void Main(string[] args)
    {
        if (mutex.WaitOne(TimeSpan.Zero, true))
        {
            App app = new App();
            app.InitializeComponent();
            app.Run();
        }
        else
        {
            MessageBox.Show("only one instance at a time");
        }
    }
}

这很好,但我想显示 MainWindow 而不是消息,所以我尝试了

static Application app;//change app to static
if (mutex.WaitOne(TimeSpan.Zero, true))
        {
            app = new App();
            app.InitializeComponent();
            app.Run();
        }  
else
{
    app.MainWindow.WindowState = WindowState.Normal;
}

我得到“System.NullReferenceException:对象引用未设置为对象的实例”。似乎应用程序中的 MainWindow(它是静态的)为空,我不明白为什么。

所以我尝试了这篇文章http://sanity-free.org/143/csharp_dotnet_single_instance_application.html 但是 WndProc 方法在 WPF 中不存在。

如果您能帮助我,我将不胜感激。 谢谢!

【问题讨论】:

  • 因为首先需要创建实例 App 和 Mainwindow。

标签: c# wpf mutex single-instance


【解决方案1】:

我创建了一个示例 WPF 应用程序,并且只更改了 App.xaml.cs 文件。如果单实例窗口已经打开,这段代码将查找与当前进程名称匹配的任何进程,如果该进程有窗口,则显示它:

public partial class App : Application
{
    // signals to restore the window to its normal state
    private const int SW_SHOWNORMAL = 1;

    // create the mutex
    private const string MUTEXNAME = "FirstInstance";
    private readonly Mutex _mutex = new Mutex(true, MUTEXNAME);

    public App()
    {
        if (!_mutex.WaitOne(TimeSpan.Zero))
        {
            ShowExistingWindow();
            Shutdown();
        }
    }

    [DllImport("User32.dll")]
    private static extern bool SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    // shows the window of the single-instance that is already open
    private void ShowExistingWindow()
    {
        var currentProcess = Process.GetCurrentProcess();
        var processes = Process.GetProcessesByName(currentProcess.ProcessName);
        foreach (var process in processes)
        {
            // the single-instance already open should have a MainWindowHandle
            if (process.MainWindowHandle != IntPtr.Zero)
            {
                // restores the window in case it was minimized
                ShowWindow(process.MainWindowHandle, SW_SHOWNORMAL);

                // brings the window to the foreground
                SetForegroundWindow(process.MainWindowHandle);

                return;
            }
        }
    }
}

仅供参考,这在调试模式下不起作用,因为 .vshost 成为进程名称的一部分。如果需要它在调试模式下工作,则需要遍历所有进程,而不是调用 Process.GetProcessesByName。

【讨论】:

    【解决方案2】:

    如果我没有误解你的问题,试试这样的

    [STAThread]
        public static void Main(string[] args)
        {
            Task task = new Task(() => { Thread.Sleep(200); MessageBox.Show("what a marvelous engineering"); });
            task.Start();
            //If you want application not to run untill task is complete then just use wait
            task.Wait();
    
                App app = new App();
                app.InitializeComponent();
                app.Run();
        }
    

    但我想知道您是否希望在 MainWindow 实例化之前完成 C# 工作,为什么不直接在 App app=new App() 之前完成其他工作并让代码按顺序运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-28
      相关资源
      最近更新 更多