Предыстория: я изо всех сил пытаюсь добавить возможности командной строки и пакетной обработки к существующему приложению Windows WPF. Когда я обнаруживаю некоторые параметры при запуске, я подавляю появление окна, выполняю некоторую обработку и немедленно закрываю. Теперь, поскольку нет пользовательского интерфейса, я хотел бы вывести некоторые сообщения на stdout / stderr. Рассмотрим следующий код:
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);
}
}
}
Когда я запускаю из командной строки, я ожидаю следующего вывода:
Start
Stop
Но вместо:
C:\test>WpfConsoleTest.exe
C:\test>
Однако вы можете перенаправить вывод:
C:\test>WpfConsoleTest.exe > out.txt
C:\test>type out.txt
Start
Stop
К сожалению, перенаправление на CON не работает:
C:\test>WpfConsoleTest.exe > CON
C:\test>
Другая проблема заключается в том, что WpfConsoleTest.exe завершает работу немедленно после запуска. Так:
C:\test>WpfConsoleTest.exe > out.txt & type out.txt
C:\test>
Но:
C:\test>WpfConsoleTest.exe > out.txt & ping localhost > nul & type out.txt
Start
Stop
Лучшее решение, которое мне удалось найти до сих пор, — использовать start /B /wait
:
C:\test>start /B /wait WpfConsoleTest.exe > out.txt & type out.txt
Start
Stop
Этот подход в основном подходит — если вы обернете его в летучую мышь, вы можете сохранить код ошибки и так далее. Единственный серьезный недостаток заключается в том, что вы получаете результат после завершения приложения, то есть вы не можете отслеживать прогресс, вам нужно дождаться завершения всего, что происходит.
Поэтому мой вопрос: Как выводить на родительскую консоль из WPF Windows Application? Кроме того, почему так сложно получить stdout / stderr из WPF?
Я знаю, что могу изменить тип приложения на Console Application в настройках проекта, но это имеет неприятный побочный эффект — окно консоли отображается все время, даже если вы просто дважды щелкните exe. Это решение также не годится, поскольку оно создает новую консоль, даже если приложение было запустить из cmd.
РЕДАКТИРОВАТЬ: чтобы уточнить, я хочу, чтобы мое приложение выводило на существующую консоль, если она есть, и не для создания новой, если она отсутствует.
Аналогичный вопрос: stackoverflow .com / questions / 160587 /. — person gwiazdorrr schedule 02.05.2012
Ссылка на этот вопрос была уже в последнем абзаце моего вопроса. — person gwiazdorrr schedule 02.05.2012
В прошлом я сделал его консольным приложением и вызвал P / Invoke, чтобы скрыть окно консоли, связанное с приложением, после того, как я показал свое окно WPF:
На данный момент это лучшее решение. Мне просто не нравится, что окно консоли появляется до того, как оно отображается, я думаю, что это может беспокоить и сбивать с толку обычного пользователя. — person gwiazdorrr; 02.05.2012
Классное решение, хотя я думаю, что согласен с @gwiazdorrr, но для служебных проектов я считаю приемлемым … просто не уверен в чистых производственных проектах. — person gwiazdorrr; 21.03.2013
Добавьте
using System.Diagnostics;
иusing System.Runtime.InteropServices;
для тех, кто хочет его скомпилировать и задается вопросом, в каких пространствах имен находятся команды. — person gwiazdorrr; 13.02.2015Решение, приведенное ниже, намного лучше. Сохраните это приложение Windows и AttachConsole при запуске. Таким образом, окно консоли не появится на короткое время перед пользовательским интерфейсом (не выглядит профессиональным). — person gwiazdorrr; 20.09.2015
Приложение WPF не будет иметь консоли по умолчанию, но вы можете легко создать ее, а затем писать в нее, как в консольном приложении. Раньше я использовал этот вспомогательный класс:
Чтобы использовать это в своем примере, вы должны уметь это сделать:
И теперь, если вы запустите его из командной строки, вы должны увидеть «Пуск» и «Стоп», написанные на консоли.
Да, но я увижу новое окно консоли, даже если я запущу его из командной строки. Я хочу видеть результат в существующей консоли. — person gwiazdorrr; 02.05.2012
Хммм … У меня это сработало в WinForms, но похоже, что WPF делает что-то другое. Вы можете попробовать AttachConsole (msdn .microsoft.com / en-us / library / windows / desktop /), но вам нужно будет получить дескриптор процесса, который запустил ваше приложение (предположительно cmd.exe). — person gwiazdorrr; 02.05.2012
Чтобы получить родительский процесс, это может помочь: rhyous.com/2010/04/30/ — person gwiazdorrr; 02.05.2012
Работает просто отлично. Только для новичков … Это необходимый код … protected override void OnStartup (StartupEventArgs e) {base.OnStartup (e); ConsoleHelper.AllocConsole (); } защищенное переопределение void OnExit (ExitEventArgs e) {ConsoleHelper.FreeConsole (); base.OnExit (e); } — person gwiazdorrr; 16.02.2016
Это предложение не для всех. Здесь мы всегда создаем новую консоль с помощью AllocConsole, независимо от того, открыта ли она у нас. Это означает, что вы по-прежнему не можете console.writeline в командной строке, когда вы запускаете приложение WPF из командной строки, а в конце программы все сообщения исчезают (поскольку дополнительная консоль была закрыта). — person gwiazdorrr; 24.11.2016
Я сделал это, но я просто вижу окно консоли без слов. Я попробовал также покрасить консоль — но она осталась черной. — person gwiazdorrr; 25.07.2017
Это работает только один раз. Если я снова запущу его, у меня вылетит. Как это исправить? — person gwiazdorrr; 07.12.2020
В свойствах проекта вы можете изменить тип проекта с приложения Windows на консольное приложение, и, как ни странно, единственное отличие состоит в том, что вы получаете консоль для использования на протяжении всего жизненного цикла приложения. Однако я не пробовал это с WPF.
Если вы хотите открывать и закрывать консоль, вам следует использовать
Alloc/FreeConsole
, но обычно проще изменить тип проекта.Как я уже писал, переход на консольное приложение создаст окно консоли, если вы дважды щелкните exe. Я хочу, чтобы вывод выводился на существующую консоль, если ее нет, не создавайте новую. — person gwiazdorrr; 02.05.2012
Немного покопавшись, я нашел этот ответ. Код сейчас:
Непосредственный вызов exe по-прежнему имеет неприятный побочный эффект, связанный с немедленным возвратом вызова:
Решением снова является использование start:
Спасибо за вклад!
Спасибо, gwiazdorrr. Это, наверное, лучшее решение. Но я все еще недоволен тем неприятным эффектом, который это вызывает. Может быть, вы нашли лучшее решение? — person gwiazdorrr; 13.10.2013
@BorisModylevsky: Боюсь, что нет, я остановился на версии
start
, вызываемой пакетным скриптом. — person gwiazdorrr; 14.10.2013Отлично, намного лучше, чем изменить приложение на консоль и скрыть окно консоли при запуске (ужасный опыт, поскольку окно консоли появится на короткое время до открытия пользовательского интерфейса) — person gwiazdorrr; 20.09.2015
Проблема с AttachConsole заключается в том, что после завершения работы приложения пользователь должен нажать «Enter», чтобы продолжить работу с консолью (кажется, что она зависла). Вы можете вызвать SendKeys.SendWait ({ENTER}); в конце, чтобы освободить консоль. — person gwiazdorrr; 20.09.2015
Я сделал это, но не вижу окно консоли — person gwiazdorrr; 25.07.2017
Я так рад, что нашел это, наткнулся на некоторые ужасно сложные обходные пути. У меня отлично получилось получить стандартный вывод из приложения C # WPF для Windows. Консольное ожидание ввода в конце не повлияло на мой вариант использования, поскольку я запускаю приложение WPF из другого приложения WPF и перенаправляю стандартный вывод из одного приложения WPF в другое. — person gwiazdorrr; 20.03.2020
Перед выходом я печатал текст «Приостановлено». Нажмите Enter, чтобы продолжить. или что-то в этом роде, чтобы пользователю было понятно, что нужно нажать Enter. — person gwiazdorrr; 25.09.2020