问题描述
我制作了一个在 .NET Framework 4.0 上运行的 WinForms 应用程序.在调用(一次,在启动时)Win32 API 函数 AttachConsole(-1)
之后,它使用 Console.WriteLine()
方法在父控制台上写入.
I made a WinForms application running on the .NET Framework 4.0. It writes on the parent console using the Console.WriteLine()
method, after calling (once, at startup) the Win32 API function AttachConsole(-1)
.
只要我只需要在屏幕上显示输出,它就可以完美运行.不幸的是,当我像这样使用带有管道重定向运算符的批处理时:
It works flawlessly as long as I just need to show the output on screen. Unfortunately when I use a batch with a pipe redirection operator like this:
application.exe > output.txt
它只是创建一个空文件.当我使用 AttachConsole
时,可能存在一些与正在处理的实际管道相关的问题?为什么命令提示符捕捉不到数据并放到文件中?有谁知道与这种情况相关的任何问题?
it just creates an empty file. Maybe there's some problem related to the actual pipe being addressed when I use AttachConsole
? Why the command prompt can't catch the data and put it on the file? Does anyone know about any problems related to such a scenario?
推荐答案
Console.Out
被延迟初始化.第一次引用它时,运行时调用 GetStdHandle(STD_OUTPUT_HANDLE)
来获取标准输出句柄.如果此调用发生在对 AttachConsole
的调用之前,您将获得该文件的句柄以进行重定向.如果之后发生此调用,您将获得控制台输出句柄.
Console.Out
is initialised lazily. The first time you reference it the runtime calls GetStdHandle(STD_OUTPUT_HANDLE)
to get the standard output handle. If this call occurs before the call to AttachConsole
you get the handle to the file for redirection. If this call occurs afterwards you get the console output handle.
以下类修复了标准输出和错误句柄.如果您从控制台启动应用程序,您会注意到在下一个提示之后会出现任何输出.您可以使用 start/wait
来避免这种情况.
The following class fixes up the standard output and error handles. If you launch your application from a console you'll notice that any output appears after the next prompt. You can avoid this with start /wait
.
using System;
using System.Runtime.InteropServices;
namespace SomeProject
{
class GuiRedirect
{
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AttachConsole(int dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetStdHandle(StandardHandle nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetStdHandle(StandardHandle nStdHandle, IntPtr handle);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern FileType GetFileType(IntPtr handle);
private enum StandardHandle : uint
{
Input = unchecked((uint)-10),
Output = unchecked((uint)-11),
Error = unchecked((uint)-12)
}
private enum FileType : uint
{
Unknown = 0x0000,
Disk = 0x0001,
Char = 0x0002,
Pipe = 0x0003
}
private static bool IsRedirected(IntPtr handle)
{
FileType fileType = GetFileType(handle);
return (fileType == FileType.Disk) || (fileType == FileType.Pipe);
}
public static void Redirect()
{
if (IsRedirected(GetStdHandle(StandardHandle.Output)))
{
var initialiseOut = Console.Out;
}
bool errorRedirected = IsRedirected(GetStdHandle(StandardHandle.Error));
if (errorRedirected)
{
var initialiseError = Console.Error;
}
AttachConsole(-1);
if (!errorRedirected)
SetStdHandle(StandardHandle.Error, GetStdHandle(StandardHandle.Output));
}
}
}
这篇关于AttachConsole() 显示管道上的数据,但 >操作员未正确重定向到文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!