C++ 从另一个进程附加和使用控制台的代码有什么问题?

C++ 从另一个进程附加和使用控制台的代码有什么问题?,c++,winapi,ipc,C++,Winapi,Ipc,我有一个服务器进程,它的分配控制台,并将输出和输入重定向到那个控制台。使用ShellExecute这个服务器进程生成一些客户机,这些客户机知道服务器进程ID。因此,我在下一个类中尝试AttachConsole: Console::Console(DWORD dwProcessId) { if (dwProcessId) { AttachConsole(dwProcessId); } else AllocConsole(); CON

我有一个服务器进程,它的分配控制台,并将输出和输入重定向到那个控制台。使用ShellExecute这个服务器进程生成一些客户机,这些客户机知道服务器进程ID。因此,我在下一个类中尝试AttachConsole:

Console::Console(DWORD dwProcessId)
{
    if (dwProcessId) {
        AttachConsole(dwProcessId);
    }
    else
        AllocConsole();

    CONSOLE_SCREEN_BUFFER_INFO coninfo;
    GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
    coninfo.dwSize.Y = 500;
    SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);

    int hConHandle;
    long lStdHandle;
    lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    FILE *fp = _fdopen( hConHandle, "w" );
    *stdout = *fp;
    setvbuf( stdout, NULL, _IONBF, 0 );

    std::ios::sync_with_stdio();
}

Console::~Console()
{
    FreeConsole();
}

但它不起作用,它甚至从服务器进程中删除到控制台的输出。隐马尔可夫模型。。可能只有一个进程可以输出到控制台。可以从多个进程向控制台发送输出吗?

您应该使用
CreateFile
打开
CONOUT$
。附加到控制台不会更改进程继承的标准句柄。

您应该使用
CreateFile
打开
CONOUT$
。附加到控制台不会更改进程继承的标准句柄。

有人能告诉我为什么接下来的更改会使我的代码正常工作:

Console::Console(DWORD dwProcessId)
{
    if (dwProcessId) {
        AttachConsole(dwProcessId);
        HANDLE consoleHandle = CreateFileA("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
        if (consoleHandle == INVALID_HANDLE_VALUE)
            throw 1;
        if (!SetStdHandle(STD_OUTPUT_HANDLE, consoleHandle)) 
            throw 2;
    }
    else {
        AllocConsole();
        CONSOLE_SCREEN_BUFFER_INFO coninfo;
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
        coninfo.dwSize.Y = 500;
        SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
    }


    int hConHandle;
    long lStdHandle;
    lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    FILE *fp = _fdopen( hConHandle, "w" );
    *stdout = *fp;
    setvbuf( stdout, NULL, _IONBF, 0 );
    }

现在,使用ShellExecute创建的客户端可以写入服务器控制台。

有人能告诉我,为什么接下来的更改会使我的代码正常工作:

Console::Console(DWORD dwProcessId)
{
    if (dwProcessId) {
        AttachConsole(dwProcessId);
        HANDLE consoleHandle = CreateFileA("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
        if (consoleHandle == INVALID_HANDLE_VALUE)
            throw 1;
        if (!SetStdHandle(STD_OUTPUT_HANDLE, consoleHandle)) 
            throw 2;
    }
    else {
        AllocConsole();
        CONSOLE_SCREEN_BUFFER_INFO coninfo;
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
        coninfo.dwSize.Y = 500;
        SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
    }


    int hConHandle;
    long lStdHandle;
    lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
    FILE *fp = _fdopen( hConHandle, "w" );
    *stdout = *fp;
    setvbuf( stdout, NULL, _IONBF, 0 );
    }

现在,使用ShellExecute创建的客户端可以写入服务器控制台。

如果这会擦除控制台,那么它就可以工作了。更改您不拥有的控制台的屏幕缓冲区是不明智的。当拥有控制台的进程也在写入时,写入也是如此。谢谢,我将控制台\屏幕\缓冲区\信息替换到调用AllocConsole的else部分。但它仍然不起作用。如果这抹去了控制台,那么它就起作用了。更改您不拥有的控制台的屏幕缓冲区是不明智的。当拥有控制台的进程也在写入时,写入也是如此。谢谢,我将控制台\屏幕\缓冲区\信息替换到调用AllocConsole的else部分。但它仍然不起作用。下一个代码也不起作用,根本没有输出,即使我只有一个没有客户端的服务器`HANDLE consoleHandle=CreateFileA(“CONOUT$”,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);if(consoleHandle==无效的句柄值)抛出1;如果(!SetStdHandle(标准输出句柄,控制台句柄))抛出2`抱歉,但是从何处继承句柄?我使用ShellExecute启动客户机,但不使用CreateProcess。谢谢。ShellExecute最终调用CreateProcess。如果您将客户端和服务器编译为控制台应用程序,您将不需要处理控制台。下一个代码也不起作用,即使只有没有客户端的服务器`HANDLE consoleHandle=CreateFileA(“CONOUT$”,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);if(consoleHandle==无效的句柄值)抛出1;如果(!SetStdHandle(标准输出句柄,控制台句柄))抛出2`抱歉,但是从何处继承句柄?我使用ShellExecute启动客户机,但不使用CreateProcess。谢谢。ShellExecute最终调用CreateProcess。如果将客户端和服务器编译为控制台应用程序,则无需处理控制台。