Extra consoles

I just finished this short class, and thought someone might find it useful. What it does is open new consoles to which an application can send output. Very useful for debugging and it avoids jamming all the output into a single console.
It works by having the server (the program that sends the output) start a client in a new process and a new console. The two are connected by an anonymous pipe. The server kills the client when the destructor is called, but if the server dies without calling it, Windows sends messages of zero length through the pipe, which tells the client to end.

Server:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class VirtualConsole{
	HANDLE near_end, //Our end of the pipe, where we'll write.
		far_end, //The other end.
		process; //The client.
public:
	bool good;
	VirtualConsole(const std::string &name,ulong color);
	~VirtualConsole();
	void put(const char *str,size_t size=0);
	void put(const std::string &str){
		this->put(str.c_str(),str.size());
	}
};

VirtualConsole::VirtualConsole(const std::string &name,ulong color){
	this->good=0;
	SECURITY_ATTRIBUTES sa;
	sa.nLength=sizeof(SECURITY_ATTRIBUTES);
	sa.bInheritHandle=1;
	sa.lpSecurityDescriptor=0;
	if (!CreatePipe(&this->far_end,&this->near_end,&sa,0)){
		assert(this->near_end==INVALID_HANDLE_VALUE);
		return;
	}
	SetHandleInformation(this->near_end,HANDLE_FLAG_INHERIT,0);
	PROCESS_INFORMATION pi;
	STARTUPINFO si;
	ZeroMemory(&pi,sizeof(pi));
	ZeroMemory(&si,sizeof(si));
	si.cb=sizeof(STARTUPINFO);
	si.hStdInput=this->far_end;
	si.dwFlags|=STARTF_USESTDHANDLES;
	TCHAR program[]=TEXT("console.exe");
	TCHAR arguments[100];
#ifndef UNICODE
	sprintf(arguments,"%d",color);
#else
	swprintf(arguments,L"0 %d",color);
#endif
	if (!CreateProcess(program,arguments,0,0,1,CREATE_NEW_CONSOLE|CREATE_UNICODE_ENVIRONMENT,0,0,&si,&pi))
		return;
	this->process=pi.hProcess;
	CloseHandle(pi.hThread);
	this->good=1;

	this->put(name);
	this->put("\n",1);
}

VirtualConsole::~VirtualConsole(){
	if (this->near_end!=INVALID_HANDLE_VALUE){
		if (this->process!=INVALID_HANDLE_VALUE){
			TerminateProcess(this->process,0);
			CloseHandle(this->process);
		}
		CloseHandle(this->near_end);
		CloseHandle(this->far_end);
	}
}
	
void VirtualConsole::put(const char *str,size_t size){
	if (!this->good)
		return;
	if (!size)
		size=strlen(str);
	DWORD l;
	WriteFile(this->near_end,str,size,&l,0);
}

Client:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <windows.h>

#define BUFSIZE 4096

int main(int argc,char **argv){
	CHAR chBuf[BUFSIZE];
	DWORD dwRead;
	HANDLE hStdin;
	BOOL fSuccess;

	hStdin = GetStdHandle(STD_INPUT_HANDLE);
	if (hStdin == INVALID_HANDLE_VALUE)
		ExitProcess(1);

	HANDLE out=CreateFile(TEXT("CONOUT$"),GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
	if (out==INVALID_HANDLE_VALUE)
		return 1;
	if (argc>1){
		WORD color=atoi(argv[1]);
		SetConsoleTextAttribute(out,color);
	}

	while (1){
		fSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL);
		if (!fSuccess || !dwRead)
			break;
		WriteFile(out,chBuf,dwRead,&dwRead,0);
	}
}
So this allows you to have multiple consoles open and print text to each one individually? Cool.
Shouldn't lines 28/29 be SecureZeroMemory(/* ... */)

And cool program, I will have to give this a try!
It's just a call to memset(). The only reason I didn't use memset() was because I was copying from an example.
I assume this is Windows only? Do you know any way to create a Linux alternative?
It's probably possible, but it'll be more complicated because neither the windowing system nor the terminal (that is, things like xterm and Konsole) are integral parts of the system.
Alright, that's what I thought. Oh well.
Topic archived. No new replies allowed.