将WPF窗口应用程序中的Output Console.WriteLine输出到实际控制台
将WPF窗口应用程序中的Output Console.WriteLine输出到实际控制台
背景:我正在努力为一个现有的WPF Windows应用程序添加命令行和批处理功能。当我在启动时检测到一些选项时,我会禁止窗口出现,进行一些处理并立即退出。现在,因为没有UI,我希望将一些消息输出到stdout/stderr。考虑以下代码:
namespace WpfConsoleTest { public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { Console.WriteLine("开始"); System.Threading.Thread.Sleep(1000); Console.WriteLine("停止"); Shutdown(0); } } }
当我从命令行运行时,我希望得到以下输出:
开始 停止
但实际上是:
C:\test>WpfConsoleTest.exe C:\test>
不过,你可以重定向输出:
C:\test>WpfConsoleTest.exe > out.txt C:\test>type out.txt 开始 停止
不幸的是,重定向到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 /B /wait
:
C:\test>start /B /wait WpfConsoleTest.exe > out.txt & type out.txt 开始 停止
这种方法大部分都可以——如果你将其封装在一个批处理文件中,可以保留错误代码等等。唯一的问题是,你在应用程序结束后才能获得输出,也就是说,你无法跟踪进度,必须等待正在进行的任何操作完成。
因此,我的问题是:如何从WPF Windows应用程序输出到父控制台?此外,为什么从WPF获取stdout/stderr这么困难?
我知道我可以在项目设置中将应用程序类型更改为控制台应用程序,但这会有一个讨厌的副作用——即使只是双击exe文件,控制台窗口也会一直可见。这个解决方案也行不通,因为即使从cmd运行应用程序,它也会创建一个新的控制台。
编辑:为了澄清,我希望我的应用程序输出到现有的控制台,而不是如果缺少控制台则创建一个新的。
问题的出现原因是WPF应用程序默认没有控制台,但是可以通过创建一个控制台来实现在应用程序中输出到控制台的功能。解决方法是使用一个辅助类ConsoleHelper来实现创建和释放控制台的功能。通过调用ConsoleHelper.AllocConsole()方法来创建控制台,并使用Console.WriteLine()方法向控制台输出内容。然后通过调用ConsoleHelper.FreeConsole()方法来释放控制台。这样,在命令行中运行应用程序时,就可以在控制台中看到输出的内容。
然而,有用户提出在使用这种方法时,会出现新的控制台窗口,而不是在已有的控制台中显示输出的问题。另一位用户提出在使用WPF时,可能需要使用AttachConsole方法,并获取启动应用程序的进程句柄来解决这个问题。他还提供了一个链接,介绍了如何获取父进程的方法。
另外还有用户提出了一种修改后的解决方案,只在没有打开控制台的情况下才创建新的控制台,并在程序退出时释放控制台。这种方法可以避免重复创建控制台和控制台窗口闪烁的问题。
还有一位用户提到在使用上述方法时,控制台窗口无法显示输出内容,并尝试添加颜色效果但无效的问题。
最后,还有一位用户提到使用上述方法只能运行一次,再次运行时会崩溃的问题,并询问如何解决。
对于无法将输出重定向到文件的问题,目前没有提出其他解决方法。
原因是WPF应用程序默认没有控制台,解决方法是使用ConsoleHelper类创建和释放控制台。然而,这种方法可能会在新的控制台窗口中显示输出内容,而不是在已有的控制台中显示。另外,还有一些其他问题,如无法显示输出内容、无法重定向输出到文件和多次运行时崩溃等。
从上述内容中,我们可以看到这个问题的出现原因是在WPF Windows应用程序中,当显示WPF窗口之前,会出现一个关联的控制台窗口。这可能对普通用户来说是令人困惑和干扰的。
为了解决这个问题,可以使用P/Invoke调用Win32 API来隐藏应用程序关联的控制台窗口。具体的解决方法如下:
1. 在代码中添加以下命名空间:
using System.Diagnostics;
using System.Runtime.InteropServices;
2. 创建一个名为Win32的类,该类包含一个静态方法HideConsoleWindow()。
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 } } }
3. 在显示WPF窗口之前,调用Win32.HideConsoleWindow()方法,以隐藏控制台窗口。
通过以上步骤,可以解决在WPF Windows应用程序中显示控制台窗口的问题,使得控制台窗口不会在显示WPF窗口之前出现。这样可以提高用户体验,使得应用程序在启动时更加专业。
问题:如何将WPF Windows应用程序的输出从Output Console.WriteLine到实际的控制台?
原因:调用WPF Windows应用程序的exe文件时,会出现一个问题,即调用会立即返回,并且光标会停留在那里等待用户按下回车键。
解决方法:通过使用"start"命令来调用exe文件,并添加"/wait"参数。这样可以解决立即返回的问题,并且光标不再停留等待用户输入。
其他解决方法:
- 将WPF应用程序更改为控制台应用程序,并在启动时隐藏控制台窗口。但这种方法体验不佳,因为控制台窗口在UI打开之前会短暂出现。
- 在应用程序完成后,调用SendKeys.SendWait("{ENTER}")来释放控制台。但有用户反馈称,该方法没有显示控制台窗口。
建议:在应用程序退出之前,打印一条消息,如"Paused. Press enter to resume.",以提示用户按下回车键。