Повторное открытие окна WPF из приложения консоли

Я хочу открыть окно WPF из приложения консоли. После ссылки на этот пост, он отлично работает.

Проблема заключается в следующем: когда пользователь закрыл окно WPF (вручную), он не может быть повторно открыт с консоли, бросая сообщение об ошибке: "Невозможно создать более одного экземпляра System.Windows.Application в том же AppDomain."

Вот код:

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?

Ответ 1

Вам не следует создавать приложение вместе с окном, но только один раз отдельно, также убедитесь, что он не выходит после закрытия окна, установив 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;, а затем просто вызвать Hide на окно "закрыть" и Show "снова открыть" его позже.

Ответ 2

Когда вы добавляете окно в качестве параметра в 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

У меня не было возможности проверить это самостоятельно, но после прочтения вашей ошибки я нашел некоторую информацию. В принципе, похоже, что AppDomain, в котором вы работаете, может использоваться только один раз для каждого приложения - поэтому, возможно, вам нужно создать новый AppDomain каждый раз, когда вы хотите повторно создать приложение. См. здесь для получения дополнительной информации об этом.

В качестве альтернативы вы можете использовать System.Diagnostics.Process.Start(...) для правильного запуска приложения. Обратитесь здесь к документации для класса Process.

Наконец, если вы просто хотите разрешить пользователю запускать приложение из командной строки, может быть проще написать команду script и выполнить это из командной строки.