如何写入第二个控制台

How do you write to a second console?

本文关键字:控制台 第二个 何写入      更新时间:2023-10-16

我的想法是在我的程序中使用第二个控制台来记录编程活动。我在msdn上查找了相关的功能/示例,并尝试将一个简单的程序放在一起:

//function in parent that communicates with child
void writeToChild()
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
HANDLE inWrite, inRead,
       outWrite, outRead;
SECURITY_ATTRIBUTES saAttr;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
if (!CreatePipe(&inRead, &inWrite, &saAttr, 0))
{
    exit(0xbad);
}
if ( ! SetHandleInformation(inRead, HANDLE_FLAG_INHERIT, 0) )
{
    exit(0xbad);
}
if (!CreatePipe(&outRead, &outWrite, &saAttr, 0))
{
    exit(0xbad);
}
if ( ! SetHandleInformation(outRead, HANDLE_FLAG_INHERIT, 0) )
{
    exit(0xbad);
}
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
si.lpTitle = "Log";
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = outWrite;
si.hStdError = outWrite;
si.hStdInput = inRead;
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( NULL,   
    "Logger",          
    NULL,        
    NULL,       
    TRUE,       
    CREATE_NEW_CONSOLE,             
    NULL,           
    NULL,           
    &si,            
    &pi )          
)
{
    printf( "CreateProcess failed (%d).n", GetLastError() );
    exit(0xbad);
}
unsigned long numWritten = 0;
WriteFile(inWrite, "Test", 4, &numWritten, NULL);
cout<<"wrote "<<numWritten<<" characters"<<endl;
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
//Logger
#include <windows.h>
#define BUFSIZE 4096
int main()
{
HANDLE stdin, stdout;
stdin = GetStdHandle(STD_INPUT_HANDLE);
stdout = GetStdHandle(STD_OUTPUT_HANDLE);
char buffer[BUFSIZE];
unsigned long numRead;
while (true)
{
    ReadFile(stdin, buffer, BUFSIZE, &numRead, NULL);
    if (numRead > 0)
        WriteFile(stdout, buffer, numRead, NULL, NULL);
}
return 0;
}

问题是,虽然父控制台显示写入了 4 个字符,但子控制台上没有显示任何内容。我不确定如何进行调试,因为我几乎没有 Windows 编程经验。

我不太确定您将在代码片段中的单独进程上走向何方。但是,您不能将多个控制台与 Windows 中的单个进程关联,尽管您可以将多个屏幕缓冲区与单个控制台关联并在它们之间切换(请参阅SetConsoleActiveScreenBuffer并从那里开始),但您必须实现该切换的用户界面;这不是内置的东西。

如果屏幕缓冲区对您不起作用,您可以有第二个记录器进程,您可以通过管道或环回套接字或其他一些 IPC 方法与之通信,例如:

  • 您可以使用 syslog,这是各种应用程序和硬件使用的常见日志记录工具。

  • 您还可以写入日志文件并使用程序来监视该文件,例如 Windows 相当于 tail -f 。这样做的好处是将记录的数据存储在文件中,以便以后查看。

  • 您可以让您的应用程序充当 TCP 服务器,远程登录到它,并通过 telnet 转储日志消息。

请注意,对于上述任何选项,为了方便用户,您可以让应用程序单独启动第二个日志监视进程(只需对ShellExecute进行简单的调用,不要过分)。

其他选项包括:

  • 您可以使用 Windows 事件日志,尽管它可能有点麻烦。

  • 您可以创建一个单独的 GUI 窗口,其中包含显示日志消息的文本字段或列表。

  • 如果您的程序是一个没有自己的控制台的 GUI 应用程序(从您的描述来看,情况似乎并非如此,但只是为了完整起见),您可以为它创建一个带有AllocConsole和朋友的控制台(但请注意,在控制台仍处于连接状态时关闭该控制台也会终止您的应用程序)。

这里有很多选择。但是,您不能为同一进程使用两个控制台。

以下是我如何做到这一点的摘要:

//parent process
YourString pipeName = format(L"\\.\pipe\%s", pName);
HANDLE hPipe = CreateNamedPipe(pipeName, /*dwOpenMode*/PIPE_ACCESS_OUTBOUND, 
    /*dwPipeMode*/PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
    /*nMaxInstances*/PIPE_UNLIMITED_INSTANCES,
    /*nOutBufferSize*/10000, /*nInBufferSize*/10000, /*nDefaultTimeOut*/50, 
    /*lpSecurityAttributes*/NULL);
//[check return value]
PROCESS_INFORMATION pi = {};
STARTUPINFOW si = {};
YourString commandLine = format(L""%s" "%s"", childProcessExeFileName, pipeName);
HANDLE hProcess = CreateProcess(
        /*lpApplicationName*/NULL, /*lpCommandLine*/commandLine,
        /*lpProcessAttributes*/NULL, /*lpThreadAttributes*/NULL,
        /*bInheritHandles*/TRUE, /*dwCreationFlags*/CREATE_NEW_CONSOLE,
        /*lpEnvironment*/NULL, /*lpCurrentDirectory*/NULL,
        &si, &pi);
//[check return value]
lpBuffer = ...
nNumberOfBytesToWrite = len(lpBuffer);
WriteFile(hPipe, lpBuffer, nNumberOfBytesToWrite, /*lpNumberOfBytesWritten*/NULL, /*lpOverlapped*/NULL);


//child process
int main(int argc, char ** argv) {
    HANDLE hPipe = CreateFile(argv[1], GENERIC_READ, 0, 
        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    //[check return value]
    ULONG PID;
    BOOL ok = GetNamedPipeServerProcessId(hPipe, &PID); 
    //[check return value]
    HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, PID);
    //[check return value]
    char buffer[1000];
    DWORD nByteRead;
    while (WaitForSingleObject(hProcess, 0) == WAIT_TIMEOUT) {
        if (hPipe) {
            ok = ReadFile(hPipe, buffer,
                sizeof(buffer) - 1, &nByteRead, NULL);
            buffer[nByteRead] = 0;
            if (!ok) {
                if (GetLastError() != ERROR_BROKEN_PIPE) ERROR();
                hPipe = NULL;
            }
            else printf("%s", buffer);
        }
        else Sleep(1000);
    }
    return 1;
}

如果你有兴趣,我可以给你发一个使用它的类,语法很简单:

WinConsole secondConsole;
secondConsole.Printf("Hello %sn", "World");

这使您可以拥有任意数量的控制台。

相关文章: