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

时间:2022-12-30 20:43:44

I want to open a WPF Window from a Console application. After referring to this post, it works fine.

我想从Console应用程序打开一个WPF窗口。在提到这篇文章后,它运作正常。

The problem is: When the user closed the WPF Window (manually), it can no long be re-opened from the Console, throwing the exception message: "Cannot create more than one System.Windows.Application instance in the same AppDomain."

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

Here is the code:

这是代码:

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();
        }
    }

How can I re-open the WPF Window?

如何重新打开WPF窗口?

3 个解决方案

#1


20  

You should not create the application together with the window but only once separately, also make sure that it does not exit after the window is closed by setting the ShutdownMode respectively, e.g.

您不应该与窗口一起创建应用程序,而只能单独创建一次,同时通过分别设置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);
    }
}

Also if you want to re-open the very same window make sure it is never closed completely, to do that you can handle the Closing event and cancel it using e.Cancel = true;, then just call Hide on the window to "close" it and Show to "open" it again later.

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

#2


0  

When you add window as a parameter to app.Run you link the lifetime of your app to your window. Don't do that:

当您将窗口作为参数添加到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.
        }

#3


0  

I've not had chance to test this myself, but after reading up on your error, I found some information. Basically, it sounds like the AppDomain you are running in can only be used once per application - so perhaps you need to create a new AppDomain each time you want to re-create the application. See here for some more information on this.

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

Alternately, you could use System.Diagnostics.Process.Start(...) in order to fire off the application properly. Refer here for the documentation for the Process class.

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

Finally, if you are just wanting to allow the user to run the application from the command line, it might be simpler to write a command script and execute that from the command line.

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

#1


20  

You should not create the application together with the window but only once separately, also make sure that it does not exit after the window is closed by setting the ShutdownMode respectively, e.g.

您不应该与窗口一起创建应用程序,而只能单独创建一次,同时通过分别设置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);
    }
}

Also if you want to re-open the very same window make sure it is never closed completely, to do that you can handle the Closing event and cancel it using e.Cancel = true;, then just call Hide on the window to "close" it and Show to "open" it again later.

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

#2


0  

When you add window as a parameter to app.Run you link the lifetime of your app to your window. Don't do that:

当您将窗口作为参数添加到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.
        }

#3


0  

I've not had chance to test this myself, but after reading up on your error, I found some information. Basically, it sounds like the AppDomain you are running in can only be used once per application - so perhaps you need to create a new AppDomain each time you want to re-create the application. See here for some more information on this.

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

Alternately, you could use System.Diagnostics.Process.Start(...) in order to fire off the application properly. Refer here for the documentation for the Process class.

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

Finally, if you are just wanting to allow the user to run the application from the command line, it might be simpler to write a command script and execute that from the command line.

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