开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜