cout fail when used cin after redirect console stream
I want to redirect console streams to cin, cout and cerr. (its a GUI application) Well, I have written this class which do this but when use cin, cout works no more.
GetLastError says me INVALID_HANDLE VALUE
Can you explain me how fix this?
Kconsole.h
class Kconsole
{
public:
Kconsole();
~Kconsole();
void CreateConsole( void );
void CloseConsole ( void );
private:
HANDLE hin;
HANDLE hout;
HWND hwnd;
bool closed;
bool err;
ofstream n_cout;
ofstream n_cerr; // new streams
ifstream n_cin;
streambuf* old_cout;
streambuf* old_cerr; // old streams
streambuf* old_cin;
};
Class method:
void Kconsole::CreateConsole( void ){
// create a console window
int ok = AllocConsole();
if ( ok == 0 ) // check console creation
{
this->err = true;
return;
}
// redirect cout to console window
this->old_cout = cout.rdbuf();
this->n_cout.open("CONOUT$");
cout.rdbuf( this->n_cout.rdbuf() );
// redirect cerr
this->old_cerr = cerr.rdbuf();
this->n_cerr.open("CONOUT$");
cerr.rdbuf( this->n_cerr.rdbuf() );
// redirect cin
this->old_cin = cin.rdbuf();
this->n_cin.open("CONIN$");
cin.rdbuf( this->n_cin.rdbuf() );
//// set titl开发者_StackOverflow社区e
SetConsoleTitle("Console");
this->hwnd = GetConsoleWindow();
//
//// get handles
this->hin = GetStdHandle(STD_OUTPUT_HANDLE);
this->hout = GetStdHandle(STD_OUTPUT_HANDLE);
return;}
Main function
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,intnCmdShow){
// All application initialization as RegisterClass, CreateWindow...
// CreateConsole Call
cout << "\nTest string"; // ok, writes this in opened console
int n = 0;
cin >> n; // ok, get typed number
n++;
cout << "\n test finished"; // dont outputs nothing to console
// here GetLastError says INVALID_HANDLE_VALUE
cerr << "\n testing cerr" // cerr outputs in console " test finished" and "testing cerr"
}
I don't see why you're messing with std::cout
et al at all. If you redirect stdout
, stderr
and stdin
to the console you can then call std::ios::sync_with_stdio()
to make sure std::cout
, std::cerr
and std::cin
all work. E.g:
// redirect unbuffered STDIN to the console
intptr_t lStdHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
int hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
FILE *fp = _fdopen( hConHandle, "r" );
*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );
std::ios::sync_with_stdio();
Here's a great article (with source) that explains it all.
It appears that you're opening the same file twice with fstream
.
this->old_cout = cout.rdbuf();
this->n_cout.open("CONOUT$"); // open for writing #1
cout.rdbuf( this->n_cout.rdbuf() );
// redirect cerr
this->old_cerr = cerr.rdbuf();
this->n_cerr.open("CONOUT$"); // open for writing #2
cerr.rdbuf( this->n_cerr.rdbuf() );
Even if your OS supports this, now there are two separate I/O buffers trying to control the file. If you try to use both, it will result in garbled output.
Either send cout
and cerr
to different files, or use the same filebuf
for both.
this->old_cout = cout.rdbuf();
this->n_cout.open("CONOUT$");
cout.rdbuf( this->n_cout.rdbuf() );
// redirect cerr
this->old_cerr = cerr.rdbuf();
cerr.rdbuf( this->n_cout.rdbuf() ); // same filebuf
I think this is still a little wonky, but it should be supported by the standard.
Why don't you just make your app a console app? You can still create windows from a console app, but it means there will always be a console, and always be standard input and output streams.
The trouble is after use cin, cout handle is closed or released. GetLastError says code 6 (ERROR_INVALID_HANDLE)
I have tried open CONOUT$ once as you say, tried open CONERR$ instead CONOUT$ twice, perhaps close CONOUT$ handle manually via CloseHandle and Open it again with GetStdHandle(STD_OUTPUT_HANDLE) or CreateFile.
In all cases, cout don't print anything. Only when use cerr all content remaining is written.
精彩评论