从控制台应用程序重新打开WPF窗口

时间:2011-11-08 08:17:57

标签: c# .net wpf winforms console-application

我想从Console应用程序打开一个WPF窗口。在提到this post之后,它运作正常。

问题是:当用户关闭WPF窗口(手动)时,不能再从控制台重新打开它,抛出异常消息:“无法在同一个中创建多个System.Windows.Application实例应用程序域“。

以下是代码:

class Program
    {
        static void Main(string[] args)
        {
            string input=null;
            while ((input = Console.ReadLine()) == "y")
            {
                //Works fine at the first iteration,
                //But failed at the second iteration.
                StartWpfThread();
            }
        }
        private static void OpenWindow()
        {
            //Exception(Cannot create more than one System.Windows.Application instance in the same AppDomain.)
            //is thrown at the second iteration.
            var app = new System.Windows.Application();
            var window = new System.Windows.Window();
            app.Run(window);
            //User  closes the opened window manually.
        }
        private static void StartWpfThread()
        {
            var thread = new Thread(() =>
            {
                OpenWindow();
            });
            thread.SetApartmentState(ApartmentState.STA);
            thread.IsBackground = false;
            thread.Start();
        }
    }

如何重新打开WPF窗口?

3 个答案:

答案 0 :(得分:22)

您不应该与窗口一起创建应用程序,而只能单独创建一次,同时通过分别设置ShutdownMode确保窗口关闭后不会退出,例如

class Program
{
    static Application app;
    static void Main(string[] args)
    {
        var appthread = new Thread(new ThreadStart(() =>
            {
                app = new Application();
                app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
                app.Run();
            }));
        appthread.SetApartmentState(ApartmentState.STA);
        appthread.Start();

        while (true)
        {
            var key =Console.ReadKey().Key;
            // Press 1 to create a window
            if (key == ConsoleKey.D1)
            {
                // Use of dispatcher necessary as this is a cross-thread operation
                DispatchToApp(() => new Window().Show());
            }
            // Press 2 to exit
            if (key == ConsoleKey.D2)
            {
                DispatchToApp(() => app.Shutdown());
                break;
            }
        }
    }

    static void DispatchToApp(Action action)
    {
        app.Dispatcher.Invoke(action);
    }
}

此外,如果您想重新打开同一个窗口,请确保它永远不会完全关闭,为此您可以处理Closing事件并使用e.Cancel = true;取消它,然后只需致电{ {1}}在窗口上“关闭”它,然后Hide再次“打开”它。

答案 1 :(得分:0)

当您将窗口作为参数添加到app.Run时,您可以将应用的生命周期链接到窗口。不要这样做:

private static void OpenWindow()
        {
            //Exception(Cannot create more than one System.Windows.Application instance in the same AppDomain.)
            //is thrown at the second iteration.
            var app = new System.Windows.Application();
            var window = new System.Windows.Window();
            app.Run();
            window.Show();
            //User  closes the opened window manually.
        }

答案 2 :(得分:0)

我自己没有机会对此进行测试,但在阅读了您的错误后,我发现了一些信息。基本上,听起来你运行的AppDomain只能在每个应用程序中使用一次 - 所以每次你想重新创建应用程序时,你可能需要创建一个新的AppDomain。有关详细信息,请参阅here

或者,您可以使用System.Diagnostics.Process.Start(...)来正确启动应用程序。有关Process类的文档,请参阅here

最后,如果您只是想让用户从命令行运行应用程序,那么编写命令脚本并从命令行执行该命令可能会更简单。