更改默认的控制台I / O功能句柄

时间:2010-05-12 19:38:51

标签: windows winapi console handle

是否有可能以某种方式更改Windows上的标准I / O函数句柄?语言优先是C ++。如果我理解正确,通过选择控制台项目,编译器只需为您预先分配控制台,并操作所有标准I / O函数以使用它的句柄。所以,我想要做的是让一个Console应用程序实际写入另一个应用程序控制台缓冲区。我虽然可以得到第一个控制台句柄,而不是通过文件将其传递给第二个应用程序(我不太了解进程间通信,这看起来很简单)并且以某种方式使用例如第一个应用程序句柄的prinf。可以这样做吗?我知道如何获得控制台句柄,但我不知道如何将printf重定向到该句柄。它只是一个研究目的项目,以更好地了解OS背后的工作。我对printf如何知道它所关联的控制台感兴趣。

3 个答案:

答案 0 :(得分:1)

如果我理解正确,听起来您需要Windows API函数AttachConsole(pid),它将当前进程附加到PID为pid的进程所拥有的控制台。

答案 1 :(得分:0)

如果要将printf重定向到句柄(FILE *),只需执行

fprintf(handle, "...");

例如,使用printf

复制fprintf
fprintf(stdout, "...");

或错误报告

fprintf(stderr, "FATAL: %s fails", "smurf");

这也是你写文件的方式。 fprintf(file, "Blah.");

答案 2 :(得分:0)

如果我理解你的错误,你可以在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 {(1}}),那么它使用父进程的控制台处理或创建一个新的。可以在IMAGE_SUBSYSTEM_WINDOWS_CUI调用的参数中更改此行为(但仅当您在代码中启动子进程时)。您根据链接器开关/子系统定义的EXE的CreateProcess标志(请参阅http://msdn.microsoft.com/en-us/library/fcc1zstk%28VS.80%29.aspx)。