是否有可能以某种方式更改 Windows 上的标准 I/O 函数句柄?首选语言是 C++。如果我理解正确,通过选择控制台项目,编译器只需为您预先分配控制台,并操作所有标准 I/O 功能以使用其句柄。所以,我想做的是让一个控制台应用程序实际写入另一个应用程序控制台缓冲区。我虽然可以获得第一个控制台句柄,而不是通过文件将它传递给第二个应用程序(我对进程间通信知之甚少,这似乎很容易),而不是以某种方式将 prinf 与第一个应用程序句柄一起使用。这可以做到吗?我知道如何获取控制台句柄,但我不知道如何将 printf 重定向到该句柄。它只是一个学习目的的项目,以更多地了解这背后的操作系统工作。我对 printf 如何知道它所关联的控制台很感兴趣。
3 回答
如果我理解正确,听起来您需要 Windows API 函数AttachConsole(pid)
,它将当前进程附加到 PID 为 的进程所拥有的控制台pid
。
如果我理解你是正确的,你可以在http://msdn.microsoft.com/en-us/library/ms682499%28VS.85%29.aspx中找到你想要编写的应用程序的源代码。这个例子展示了如何写入stdin
另一个应用程序并读取它的stdout
.
为了一般的理解。编译器不会“为您预先分配控制台”。编译器使用写入输出的标准 C/C++ 库。因此,如果您使用例如printf()
以下代码将在最后执行将如下所示:
void Output (PCWSTR pszwText, UINT uTextLenght) // uTextLenght is Lenght in charakters
{
DWORD n;
UINT uCodePage = GetOEMCP(); // CP_OEMCP, CP_THREAD_ACP, CP_ACP
PSTR pszText = _alloca (uTextLenght);
// in the console are typically not used UNICODE, so
if (WideCharToMultiByte (uCodePage, 0, pszwText, uTextLenght,
pszText, uTextLenght, NULL, NULL) != (int)uTextLenght)
return;
WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), pszText, uTextLenght, &n, NULL);
//_tprintf (TEXT("%.*ls"), uTextLenght, pszText);
//_puttchar();
//fwrite (pszText, sizeof(TCHAR), uTextLenght, stdout);
//_write (
}
因此,如果更改STD_OUTPUT_HANDLE
所有输出的值将转到文件/管道等等。如果不是WriteFile
程序使用WriteConsole
函数,这种重定向将不起作用,但标准 C/C++ 库不这样做。
如果您不想stdout
从子进程而是从当前进程重定向,您可以SetStdHandle()
直接调用(请参阅http://msdn.microsoft.com/en-us/library/ms686244%28VS.85%29.aspx)。
“分配控制台”做一个操作系统的加载器。它看起来是二进制 EXE 文件的单词(在子系统部分IMAGE_OPTIONAL_HEADER
见http://msdn.microsoft.com/en-us/library/ms680339%28VS.85%29.aspx),如果 EXE 在这个地方有 3 ( IMAGE_SUBSYSTEM_WINDOWS_CUI
),而不是使用父进程的控制台或创建一个新的。可以在调用参数中稍微改变这种行为CreateProcess
(但前提是您在代码中启动子进程)。您Subsystem
定义的关于链接器开关 /subsystem 的 EXE 标志(请参阅http://msdn.microsoft.com/en-us/library/fcc1zstk%28VS.80%29.aspx)。
如果您想重定向printf
到句柄 (FILE*),只需执行
fprintf(handle, "...");
例如printf
复制fprintf
fprintf(stdout, "...");
或者报错
fprintf(stderr, "FATAL: %s fails", "smurf");
这也是您写入文件的方式。fprintf(file, "Blah.");