Вывести Console.WriteLine из приложений Windows WPF на реальную консоль

Справочная информация: я пытаюсь добавить возможности командной строки и пакетной обработки в существующий WPFWindows Application, При обнаружении некоторых опций при запуске я подавляю появление окна, выполняю некоторую обработку и сразу же завершаю работу. Теперь, поскольку пользовательский интерфейс отсутствует, я хотел бы выводить некоторые сообщения в stdout / stderr. Рассмотрим следующий код:

<code>namespace WpfConsoleTest
{
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            Console.WriteLine("Start");
            System.Threading.Thread.Sleep(1000);
            Console.WriteLine("Stop");
            Shutdown(0);
        }
    }
}
</code>

Когда я запускаю из командной строки, я ожидаю следующий вывод:

<code>Start
Stop
</code>

Но вместо этого:

<code>C:\test>WpfConsoleTest.exe

C:\test>
</code>

Выcan перенаправить вывод, хотя:

<code>C:\test>WpfConsoleTest.exe > out.txt

C:\test>type out.txt
Start
Stop
</code>

Перенаправление на CON не работает, к сожалению:

<code>C:\test>WpfConsoleTest.exe > CON

C:\test>
</code>

Другая проблема заключается в том, что WpfConsoleTest.exe выходитimmedietaly после старта. Так:

<code>C:\test>WpfConsoleTest.exe > out.txt & type out.txt

C:\test>
</code>

Но:

<code>C:\test>WpfConsoleTest.exe > out.txt & ping localhost > nul & type out.txt
Start
Stop
</code>

Лучшее решение, которое я смог найти, это использоватьstart /B /wait:

<code>C:\test>start /B /wait WpfConsoleTest.exe > out.txt & type out.txt
Start
Stop
</code>

Этот подход в основном нормальный - если вы завернули его в летучую мышь, вы можете сохранить код ошибки и так далее. Единственным огромным недостатком является то, что вы получаете выходные данные после завершения приложения, то есть нет никакого способа, которым вы можете отслеживать прогресс, вы должны ждать, пока все, что происходит, завершится.

Поэтому мой вопрос:How to output to parent console from WPF Windows Application? Кроме того, почему так сложно получить stdout / stderr из WPF?

Я знаю, что могу изменить тип приложения наConsole Application в настройках проекта, но это имеет неприятный побочный эффект - окно консоли видно все время, даже если вы просто дважды щелкните по exe.Это решение также не будет, потому что это создаетa new консоль, даже если приложение запускалось из cmd.

РЕДАКТИРОВАТЬ: чтобы уточнить, я хочу, чтобы мое приложение выводило наexisting консоль, если есть иnot создать новый, если он отсутствует.

 Lukasz Madon02 мая 2012 г., 16:43
Подобный вопрос:stackoverflow.com/questions/160587/…
 gwiazdorrr02 мая 2012 г., 17:20
Ссылка на этот вопрос уже была в последнем абзаце моего вопроса.

Ответы на вопрос(4)

но вы можете легко создать для нее консоль и затем писать в нее, как в консольном приложении. Я использовал этот вспомогательный класс раньше:

public class ConsoleHelper
{
    /// <summary>
    /// Allocates a new console for current process.
    /// </summary>
    [DllImport("kernel32.dll")]
    public static extern Boolean AllocConsole();

    /// <summary>
    /// Frees the console.
    /// </summary>
    [DllImport("kernel32.dll")]
    public static extern Boolean FreeConsole();
}

Чтобы использовать это в своем примере, вы должны быть в состоянии сделать это:

namespace WpfConsoleTest
{
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            ConsoleHelper.AllocConsole(); 
            Console.WriteLine("Start");
            System.Threading.Thread.Sleep(1000);
            Console.WriteLine("Stop");
            ConsoleHelper.FreeConsole();
            Shutdown(0);
        }
    }
}

И теперь, если вы запустите его из командной строки, вы должны увидеть & quot; Пуск & quot; и "Стоп" записано в консоль.

 24 нояб. 2016 г., 15:31
Это предложение не решение для всех. Здесь мы всегда создаем новую консоль с AllocConsole независимо от того, есть ли у нас уже открытая. Это означает, что вы все равно не можете сохранить console.writeline в командной строке при запуске приложения WPF из командной строки и в конце программы все сообщения исчезают (поскольку дополнительная консоль была закрыта).
 gwiazdorrr02 мая 2012 г., 17:19
Да, но я увижуnew окно консоли, даже если я запускаю его из командной строки. Я хочу увидеть результат вexisting приставка.
 02 мая 2012 г., 19:19
Хммм ... Это хорошо сработало для меня в WinForms, но кажется, что WPF делает что-то другое. Вы можете попробовать AttachConsole (msdn.microsoft.com/en-us/library/windows/desktop/…), но вам нужно получить дескриптор процесса, который запустил ваше приложение (предположительно, cmd.exe)
 02 мая 2012 г., 19:23
Чтобы получить родительский процесс, это может помочь:rhyous.com/2010/04/30/…
 16 февр. 2016 г., 04:37
Работает просто отлично. Просто для некоторых новичков ... Это необходимый код ... защищенное переопределение void OnStartup (StartupEventArgs e) {base.OnStartup (e); ConsoleHelper.AllocConsole (); } защищенное переопределение void OnExit (ExitEventArgs e) {ConsoleHelper.FreeConsole (); base.OnExit (е); }

чтобы скрыть окно консоли, связанное с приложением, после того как я показал свое окно WPF:

//added using statements per comments...
using System.Diagnostics;
using System.Runtime.InteropServices;

    internal sealed class Win32
    {
        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        public static void HideConsoleWindow()
        {
            IntPtr hWnd = Process.GetCurrentProcess().MainWindowHandle;

            if (hWnd != IntPtr.Zero)
            {
                ShowWindow(hWnd, 0); // 0 = SW_HIDE
            }
        }
    }
 13 февр. 2015 г., 12:18
добавлятьusing System.Diagnostics; а такжеusing System.Runtime.InteropServices; для тех, кто хочет его скомпилировать и интересуется, в каких пространствах имен находятся команды.
 gwiazdorrr02 мая 2012 г., 21:26
Это лучшее решение на сегодняшний день. Мне просто не нравится, когда окно консоли появляется перед отображаемым окном, я думаю, что оно может беспокоить и сбивать с толку обычного пользователя.
 20 сент. 2015 г., 20:55
Решение ниже гораздо лучше. Держите это приложение Windows и AttachConsole при запуске. Таким образом, окно консоли не будет отображаться на короткое время перед пользовательским интерфейсом (не выглядит профессионально)
 21 мар. 2013 г., 16:14
Отличное решение, хотя я думаю, что согласен с @gwiazdorrr, но для коммунальных проектов я думаю, что это приемлемо ... просто не уверен насчет чистого "производства" проекты.
Решение Вопроса

этот ответ, Код сейчас:

namespace WpfConsoleTest
{
    public partial class App : Application
    {
        [DllImport("Kernel32.dll")]
        public static extern bool AttachConsole(int processId);

        protected override void OnStartup(StartupEventArgs e)
        {
            AttachConsole(-1);
            Console.WriteLine("Start");
            System.Threading.Thread.Sleep(1000);
            Console.WriteLine("Stop");
            Shutdown(0);
        }
    }
}

Вызов exe напрямую все еще имеет неприятный побочный эффект, связанный с немедленным возвратом вызова:

C:\test>WpfConsoleTest.exe

C:\test>Start
Stop

^^^^
The cursor will stay here waiting for the user to press enter!

Решение, опять же, использоватьstart:

C:\test>start /wait WpfConsoleTest.exe
Start
Stop

Спасибо за вклад!

 14 окт. 2013 г., 13:23
спасибо большое @gwiazdorrr!
 13 окт. 2013 г., 08:49
Спасибо, gwiazdorrr. Это, вероятно, лучшее решение. Но я все еще не доволен тем неприятным эффектом, который он вызывает. Возможно, вы нашли лучшее решение?
 20 сент. 2015 г., 20:53
Отлично, гораздо лучше, чем переключение приложения в консоль и скрытие окна консоли при запуске (ужасный опыт, поскольку окно консоли ненадолго появится перед открытием интерфейса)
 gwiazdorrr14 окт. 2013 г., 09:40
@BorisModylevsky: боюсь, нет, я согласился сstart версия вызывается пакетным скриптом.
 20 сент. 2015 г., 21:34
Проблема с AttachConsole заключается в том, что после завершения приложения пользователь должен нажать «ввести». продолжить работу с консолью (кажется, зависает). Вы можете вызвать SendKeys.SendWait (& quot; {ENTER} & quot;); в конце освободить консоль.

s на консольное приложение, и AFAIK, единственное отличие состоит в том, что вы получаете консоль для использования в течение всего срока службы приложения. Я не пробовал это с WPF, хотя.

Если вы хотите открыть и закрыть консоль, вы должны использоватьAlloc/FreeConsole, но обычно проще изменить тип проекта.

 gwiazdorrr02 мая 2012 г., 17:21
Как я уже писал, переход на консольное приложение создаст окно консоли, если дважды щелкнуть исполняемый файл. То, что я хочу, - это вывод на печатьexisting консоль, если ее нет, не создавайте новую.

Ваш ответ на вопрос