Нет вывода на консоль из приложения WPF?
Я использую Console.WriteLine() из очень простого тестового приложения WPF, но когда я запускаю приложение из командной строки, я не вижу ничего записываемого в консоль. Кто-нибудь знает, что здесь может происходить?
Я могу воспроизвести его, создав приложение WPF в VS 2008 и просто добавив Console.WriteLine("текст") в любое место, где выполняется. Есть идеи?
Все, что мне нужно сейчас, это что-то простое, как Console.WriteLine(). Я понимаю, что могу использовать log4net или какое-то другое решение для ведения журналов, но мне действительно не нужно так много функциональности для этого приложения.
Изменить: я должен был помнить, что Console.WriteLine() для консольных приложений. Да ладно, без глупых вопросов, верно?:-) Сейчас я просто буду использовать System.Diagnostics.Trace.WriteLine() и DebugView.
12 ответов
Вам придется создать окно консоли вручную, прежде чем вы на самом деле вызовете какие-либо методы Console.Write. Это заставит Консоль работать должным образом без изменения типа проекта (который для приложения WPF не будет работать).
Вот полный пример исходного кода того, как может выглядеть класс ConsoleManager, и как его можно использовать для включения / выключения консоли независимо от типа проекта.
Со следующим классом вам просто нужно написать ConsoleManager.Show()
где-то до любого звонка Console.Write
...
[SuppressUnmanagedCodeSecurity]
public static class ConsoleManager
{
private const string Kernel32_DllName = "kernel32.dll";
[DllImport(Kernel32_DllName)]
private static extern bool AllocConsole();
[DllImport(Kernel32_DllName)]
private static extern bool FreeConsole();
[DllImport(Kernel32_DllName)]
private static extern IntPtr GetConsoleWindow();
[DllImport(Kernel32_DllName)]
private static extern int GetConsoleOutputCP();
public static bool HasConsole
{
get { return GetConsoleWindow() != IntPtr.Zero; }
}
/// <summary>
/// Creates a new console instance if the process is not attached to a console already.
/// </summary>
public static void Show()
{
//#if DEBUG
if (!HasConsole)
{
AllocConsole();
InvalidateOutAndError();
}
//#endif
}
/// <summary>
/// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown.
/// </summary>
public static void Hide()
{
//#if DEBUG
if (HasConsole)
{
SetOutAndErrorNull();
FreeConsole();
}
//#endif
}
public static void Toggle()
{
if (HasConsole)
{
Hide();
}
else
{
Show();
}
}
static void InvalidateOutAndError()
{
Type type = typeof(System.Console);
System.Reflection.FieldInfo _out = type.GetField("_out",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
System.Reflection.FieldInfo _error = type.GetField("_error",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError",
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
Debug.Assert(_out != null);
Debug.Assert(_error != null);
Debug.Assert(_InitializeStdOutError != null);
_out.SetValue(null, null);
_error.SetValue(null, null);
_InitializeStdOutError.Invoke(null, new object[] { true });
}
static void SetOutAndErrorNull()
{
Console.SetOut(TextWriter.Null);
Console.SetError(TextWriter.Null);
}
}
Ты можешь использовать
Trace.WriteLine("text");
Это выведет в окно "Вывод" в Visual Studio (при отладке).
убедитесь, что диагностическая сборка включена:
using System.Diagnostics;
Щелкните правой кнопкой мыши по проекту, "Свойства", вкладке "Приложение", измените "Тип вывода" на "Консольное приложение", и тогда у него также будет консоль.
Старый пост, но я столкнулся с этим, так что если вы пытаетесь что-то вывести в Output в проекте WPF в Visual Studio, современный метод:
Включить это:
using System.Diagnostics;
А потом:
Debug.WriteLine("something");
Хотя Джон Лейдгрен продолжает отрицать эту идею, Брайан прав. Я только что работал в Visual Studio.
Для ясности приложение WPF не создает консольное окно по умолчанию.
Вы должны создать приложение WPF, а затем изменить тип вывода на "Консольное приложение". Когда вы запустите проект, вы увидите консольное окно с окном WPF перед ним.
Это выглядит не очень красиво, но я нашел это полезным, поскольку я хотел, чтобы мое приложение запускалось из командной строки с обратной связью, а затем для определенных параметров команды я отображал окно WPF.
Можно просмотреть выходные данные, предназначенные для консоли, с помощью перенаправления командной строки.
Например:
C:\src\bin\Debug\Example.exe > output.txt
напишу весь контент output.txt
файл.
Я использую Console.WriteLine() для использования в окне вывода...
Решение Брайана состоит в том, чтобы всегда открывать консоль при запуске вашего приложения WPF. Если вы хотите динамически включить вывод консоли (например, только при запуске с определенными аргументами командной строки), вызовитеAttachConsole
:
[DllImport("kernel32.dll")]
static extern bool AttachConsole(uint dwProcessId);
const uint ATTACH_PARENT_PROCESS = 0x0ffffffff;
Затем, когда вы хотите начать запись в консоль:
AttachConsole(ATTACH_PARENT_PROCESS);
Console.WriteLine("Hello world!");
Console.WriteLine("Writing to the hosting console!");
Я создал решение, смешал информацию из сообщения varius.
Это форма, которая содержит метку и одно текстовое поле. Вывод на консоль перенаправляется в текстовое поле.
Также существует класс ConsoleView, который реализует три открытых метода: Show(), Close() и Release(). Последний - оставить консоль открытой и активировать кнопку "Закрыть" для просмотра результатов.
Форма называется FrmConsole. Вот XAML и код C#.
Использование очень просто:
ConsoleView.Show("Title of the Console");
Для открытой консоли. Использование:
System.Console.WriteLine("The debug message");
Для вывода текста на консоль.
Использование:
ConsoleView.Close();
Для закрытия консоли.
ConsoleView.Release();
Оставляет консоль открытой и активирует кнопку Закрыть
XAML
<Window x:Class="CustomControls.FrmConsole"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CustomControls"
mc:Ignorable="d"
Height="500" Width="600" WindowStyle="None" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" Topmost="True" Icon="Images/icoConsole.png">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="*"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Name="lblTitulo" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" FontFamily="Arial" FontSize="14" FontWeight="Bold" Content="Titulo"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="10"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="1" Name="txtInner" FontFamily="Arial" FontSize="10" ScrollViewer.CanContentScroll="True" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" TextWrapping="Wrap"/>
</Grid>
<Button Name="btnCerrar" Grid.Row="2" Content="Cerrar" Width="100" Height="30" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center"/>
</Grid>
Код окна:
partial class FrmConsole : Window
{
private class ControlWriter : TextWriter
{
private TextBox textbox;
public ControlWriter(TextBox textbox)
{
this.textbox = textbox;
}
public override void WriteLine(char value)
{
textbox.Dispatcher.Invoke(new Action(() =>
{
textbox.AppendText(value.ToString());
textbox.AppendText(Environment.NewLine);
textbox.ScrollToEnd();
}));
}
public override void WriteLine(string value)
{
textbox.Dispatcher.Invoke(new Action(() =>
{
textbox.AppendText(value);
textbox.AppendText(Environment.NewLine);
textbox.ScrollToEnd();
}));
}
public override void Write(char value)
{
textbox.Dispatcher.Invoke(new Action(() =>
{
textbox.AppendText(value.ToString());
textbox.ScrollToEnd();
}));
}
public override void Write(string value)
{
textbox.Dispatcher.Invoke(new Action(() =>
{
textbox.AppendText(value);
textbox.ScrollToEnd();
}));
}
public override Encoding Encoding
{
get { return Encoding.UTF8; }
}
}
//DEFINICIONES DE LA CLASE
#region DEFINICIONES DE LA CLASE
#endregion
//CONSTRUCTORES DE LA CLASE
#region CONSTRUCTORES DE LA CLASE
public FrmConsole(string titulo)
{
InitializeComponent();
lblTitulo.Content = titulo;
Clear();
btnCerrar.Click += new RoutedEventHandler(BtnCerrar_Click);
Console.SetOut(new ControlWriter(txtInner));
DesactivarCerrar();
}
#endregion
//PROPIEDADES
#region PROPIEDADES
#endregion
//DELEGADOS
#region DELEGADOS
private void BtnCerrar_Click(object sender, RoutedEventArgs e)
{
Close();
}
#endregion
//METODOS Y FUNCIONES
#region METODOS Y FUNCIONES
public void ActivarCerrar()
{
btnCerrar.IsEnabled = true;
}
public void Clear()
{
txtInner.Clear();
}
public void DesactivarCerrar()
{
btnCerrar.IsEnabled = false;
}
#endregion
}
код класса ConsoleView
static public class ConsoleView
{
//DEFINICIONES DE LA CLASE
#region DEFINICIONES DE LA CLASE
static FrmConsole console;
static Thread StatusThread;
static bool isActive = false;
#endregion
//CONSTRUCTORES DE LA CLASE
#region CONSTRUCTORES DE LA CLASE
#endregion
//PROPIEDADES
#region PROPIEDADES
#endregion
//DELEGADOS
#region DELEGADOS
#endregion
//METODOS Y FUNCIONES
#region METODOS Y FUNCIONES
public static void Show(string label)
{
if (isActive)
{
return;
}
isActive = true;
//create the thread with its ThreadStart method
StatusThread = new Thread(() =>
{
try
{
console = new FrmConsole(label);
console.ShowDialog();
//this call is needed so the thread remains open until the dispatcher is closed
Dispatcher.Run();
}
catch (Exception)
{
}
});
//run the thread in STA mode to make it work correctly
StatusThread.SetApartmentState(ApartmentState.STA);
StatusThread.Priority = ThreadPriority.Normal;
StatusThread.Start();
}
public static void Close()
{
isActive = false;
if (console != null)
{
//need to use the dispatcher to call the Close method, because the window is created in another thread, and this method is called by the main thread
console.Dispatcher.InvokeShutdown();
console = null;
StatusThread = null;
}
console = null;
}
public static void Release()
{
isActive = false;
if (console != null)
{
console.Dispatcher.Invoke(console.ActivarCerrar);
}
}
#endregion
}
Я надеюсь, что этот результат будет полезным.
У меня тоже недавно была эта проблема.
Если решение Брайана (переход на консольное приложение в настройках проекта) не устранило проблему: попробуйте изменить целевую платформу с .NET 5.0 на .NET Core 3.1.
Проверьте этот пост, было очень полезно для меня. Загрузите пример кода:
http://www.codeproject.com/Articles/335909/Embedding-a-Console-in-a-C-Application
Насколько я знаю, Console.WriteLine() предназначена только для консольных приложений. Я думаю, что это твоя проблема.