WPF 应用程序没有输出到控制台?
Posted
技术标签:
【中文标题】WPF 应用程序没有输出到控制台?【英文标题】:No output to console from a WPF application? 【发布时间】:2010-09-14 16:56:42 【问题描述】:我在一个非常简单的 WPF 测试应用程序中使用Console.WriteLine()
,但是当我从命令行执行应用程序时,我没有看到任何内容写入控制台。有谁知道这里可能发生了什么?
我可以通过在 VS 2008 中创建一个 WPF 应用程序来重现它,并在它执行的任何地方简单地添加 Console.WriteLine("text")
。有什么想法吗?
我现在只需要像Console.WriteLine()
这样简单的东西。我意识到我可以使用 log4net 或其他一些日志记录解决方案,但我真的不需要这个应用程序的那么多功能。
编辑:我应该记得Console.WriteLine()
用于控制台应用程序。哦,好吧,没有愚蠢的问题,对吧? :-)
我现在只使用System.Diagnostics.Trace.WriteLine()
和 DebugView。
【问题讨论】:
可能重复 here 和 here(较新,但使用 AttachConsole from Kernel32.dll 有一些有趣的答案) @Max,这些问题可能与 this 问题重复。这个问题是在您发布这些问题之前 2-4 年提出的。 【参考方案1】:你可以使用
Trace.WriteLine("text");
这将输出到 Visual Studio 中的“输出”窗口(调试时)。
确保包含诊断程序集:
using System.Diagnostics;
【讨论】:
这是最好的答案,但没有最高评分 我同意 - 这正是 op 所要求的。 Console.WriteLine() 的绝佳替代方案 - 标记为答案的解决方案是一个巧妙的练习,但包含在生产应用程序中是不合理的。 PS for Windows Store 应用程序(Windows 运行时)相当于 Trace.WriteLine 是 Debug.WriteLine() 这是一个简单、干净的解决方案,但对我不起作用。在更新数据库期间无法在实体框架的种子方法中工作。否则,在其他任何地方都可以使用! 这是最好的解决方案。如果答案还解释说Console.WriteLine
根本不适用于 WPF 应用程序,而仅用于命令行应用程序,那就更好了。【参考方案2】:
右击项目,“属性”,“应用程序”选项卡,将“输出类型”改为“控制台应用程序”,然后它也会有一个控制台。
【讨论】:
唯一的问题是你会在后台打开一个 cmd,但它可以工作:)。 很好,但是当应用程序不是从 cmd.exe 执行时会创建命令行窗口(为一个应用程序创建两个窗口)。但为此也有解决方案:您可以通过 ShowWindow(hWnd, 0) 隐藏 cmd 窗口。 ***.com/a/10416180/1457197 。使用此解决方案,只有在从命令行执行 WPF 应用程序时,您才会在控制台中看到文本。 请注意,在 Blend 中工作时,您必须将其切换回“窗口应用程序”,因为它仅显示“控制台应用程序”类型的 XAML(无法访问设计视图)。 (截至 2013 年的 Blend) 答案不正确。隐藏主窗口。只是控制台出现了。 谢谢!当您执行上述答案中@John Leidegren 显示的操作时,必须使用此解决方案【参考方案3】:在实际调用任何 Console.Write 方法之前,您必须手动创建一个控制台窗口。这将使控制台在不更改项目类型的情况下正常工作(对于 WPF 应用程序将不起作用)。
这是一个完整的源代码示例,说明 ConsoleManager 类的外观,以及如何使用它来启用/禁用控制台,与项目类型无关。
使用以下课程,您只需在调用Console.Write
之前在某处写ConsoleManager.Show()
...
[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);
【讨论】:
可以先尝试调用 AttachConsole(-1) 并检查其返回值以附加到父进程的控制台;如果返回 false,则调用 AllocConsole。但是,应用程序仍然首先“返回”,然后才输出到控制台,如果我找到解决方案,我会发布更多信息。此外,如果您将 WPF 应用程序类型设置为控制台应用程序,问题就会消失,但您无法在程序启动时在屏幕上短暂显示的情况下分离控制台,所以它看起来有点尴尬(但如果你能忍受它,效果很好)。 嗯,实际上不,我认为不可能同时拥有它;控制台应用程序在其 PE 标头中标记为 CUI,因此可以很好地与 CMD 自动配合。另一方面,GUI 应用程序立即将控制权返回给 CMD,即使它可以重新连接到控制台,读取和写入也会与管道中的下一个输出混合在一起,这显然是非常糟糕的。另一方面,如果您将应用程序标记为控制台应用程序,则只需在应用程序启动时短暂显示 CMD;然后,您可以使用 FreeConsole 分离并稍后附加/分配等 当 Brian 的回答也有效且容易得多时,为什么要这样做。 可能很明显,但我发现当附加了 Visual Studio 调试器时,Console.WriteLine 仍然无法使用这种技术。当我在 VS 之外运行该应用程序时,它很有效。谢谢。 @Mark 是的,但它不起作用...有一个SetConsoleCtrlHandler
函数允许在 CTRL_CLOSE_EVENT
事件发生时得到通知,但你不能用它做任何事情,有没有任何东西可以让您的应用程序继续进行。你将被关闭。如果您想破解,您可以将 Windows 消息处理程序换成控制台进程,然后删除 WM_CLOSE 消息,我从未尝试过,但它可以工作。这只是另一个窗口,但话虽如此,除非你想接受这个想法,否则你最好把精力花在做其他事情上。【参考方案4】:
旧帖子,但我遇到了这个问题,所以如果您尝试在 Visual Studio 的 WPF 项目中将某些内容输出到 Output,现代方法是:
包括这个:
using System.Diagnostics;
然后:
Debug.WriteLine("something");
【讨论】:
【参考方案5】:尽管 John Leidegren 不断否定这个想法,但 Brian 是正确的。我刚刚让它在 Visual Studio 中运行。
需要明确的是,WPF 应用程序默认情况下不会创建控制台窗口。
您必须创建一个 WPF 应用程序,然后将 OutputType 更改为“控制台应用程序”。运行项目时,您会看到一个控制台窗口,前面是您的 WPF 窗口。
它看起来不是很漂亮,但我发现它很有帮助,因为我希望我的应用程序可以从命令行运行并在其中提供反馈,然后对于某些命令选项,我会显示 WPF 窗口。
【讨论】:
完美。做这项工作。【参考方案6】:使用command line redirection 可以查看用于控制台的输出。
例如:
C:\src\bin\Debug\Example.exe > output.txt
将所有内容写入output.txt
文件。
【讨论】:
最佳答案,因为它很简单并且不需要更改源代码 ...当然,下一步是在notepad++中打开文件并选择'View -> Monitoring (tail -f)'来观看它的实时更新【参考方案7】:我使用 Console.WriteLine() 在输出窗口中使用...
【讨论】:
这是一个 4 年前的问题,自从我第一次看到它以来,它已经被大量编辑。当然,现在这个问题措辞更好,我的回答变得无关紧要。【参考方案8】:我已经创建了一个解决方案,混合了各种帖子的信息。
它是一个表单,包含一个标签和一个文本框。控制台输出被重定向到文本框。
还有一个名为 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
我希望这个结果有用。
【讨论】:
【参考方案9】:看看这篇文章,对我自己很有帮助。下载代码示例:
http://www.codeproject.com/Articles/335909/Embedding-a-Console-in-a-C-Application
【讨论】:
【参考方案10】:我最近也遇到过这个问题。
如果 Brians 解决方案(在项目设置中更改为控制台应用程序)没有解决问题:尝试将目标框架从 .NET 5.0 更改为 .NET Core 3.1。
【讨论】:
以上是关于WPF 应用程序没有输出到控制台?的主要内容,如果未能解决你的问题,请参考以下文章