我怎么能写一些已打开的控制台的标准输出?
我用这段代码找到了我需要的控制台:
IntPtr ptr = GetForegroundWindow();
int u;
GetwindowThreadProcessId(ptr, out u);
Process process = Process.GetProcessById(u);
问题是如何获得此进程的标准输出句柄指针(stdHandle).
我想要的是:
SafeFileHandle safeFileHandle = new SafeFileHandle(stdHandle, true);
FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write);
Encoding encoding = Encoding.ASCII;
StreamWriter standardOutput = new StreamWriter(fileStream, encoding);
standardOutput.AutoFlush = true;
Console.Setout(standardOutput);
使用Windows API的C代码是可以的 – 我可以使用pInvoke.
实际上我想要的是将文本写入已经打开的控制台窗口而不是由我的进程生成(并且它是通过命令行启动我的进程时处于前台的那个 – 但我的进程是WinApp,因此控制台不会附加std).
PS:我读到了一些可用于执行此操作的COM文件,因此这意味着有一种编程方式……
谢谢!
解决方法:
我最终想出了如何在启动windows应用程序时将其透明地附加到控制台(如果它是前景窗口).
不要问我为什么必须传递STD_ERROR_HANDLE而不是STD_OUTPUT_HANDLE,但它只是起作用,可能是因为可以共享标准错误.
N.B.:控制台可以在显示内部的应用程序消息时接受用户输入,但在stderr从您的应用程序输出时使用它有点令人困惑.
如果您从控制台窗口启动应用程序至少有一个参数的代码片段,它会将Console.Write附加到它,如果您使用参数/ debug启动应用程序,那么它甚至会将Debug.Write附加到安慰.
在退出应用程序之前调用Cleanup()以释放控制台并发送Enter按键以释放最后一行,以便在启动应用程序之前控制台可用.
PS.你不能使用这种方法使用输出重定向即:yourapp.exe> file.txt因为
你会得到一个空文件.甚至不尝试myapp.exe> file.txt 2>& 1因为你将崩溃应用程序(将错误重定向到输出意味着我们正在尝试连接到非共享缓冲区).
这是代码:
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetwindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
[DllImport("kernel32.dll",
EntryPoint = "GetStdHandle",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32", SetLastError = true)]
static extern bool AttachConsole(uint dwProcessId);
[DllImport("kernel32.dll",
EntryPoint = "AllocConsole",
SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int AllocConsole();
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool FreeConsole();
private const int STD_OUTPUT_HANDLE = -11;
private const int STD_ERROR_HANDLE = -12;
private static bool _consoleAttached = false;
private static IntPtr consoleWindow;
[STAThread]
static void Main()
{
args = new List<string>(Environment.GetCommandLineArgs());
int prId;
consoleWindow = GetForegroundWindow();
GetwindowThreadProcessId(consoleWindow, out prId);
Process process = Process.GetProcessById(prId);
if (args.Count > 1 && process.ProcessName == "cmd")
{
if (AttachConsole((uint)prId)) {
_consoleAttached = true;
IntPtr stdHandle = GetStdHandle(STD_ERROR_HANDLE); // must be error dunno why
SafeFileHandle safeFileHandle = new SafeFileHandle(stdHandle, true);
FileStream fileStream = new FileStream(safeFileHandle, FileAccess.Write);
Encoding encoding = Encoding.ASCII;
StreamWriter standardOutput = new StreamWriter(fileStream, encoding);
standardOutput.AutoFlush = true;
Console.Setout(standardOutput);
if (args.Contains("/debug")) Debug.Listeners.Add(new TextWriterTraceListener(Console.Out));
Console.WriteLine(Application.ProductName + " was launched from a console window and will redirect output to it.");
}
}
// ... do whatever, use console.writeline or debug.writeline
// if you started the app with /debug from a console
Cleanup();
}
private static void Cleanup() {
try
{
if (_consoleAttached)
{
SetForegroundWindow(consoleWindow);
SendKeys.SendWait("{ENTER}");
FreeConsole();
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。