我想将控制台流重定向到cin,cout和cerr。 (它的gui申请) 好吧,我已经写了这个类,但是当使用cin时,cout不再工作了。
GetLastError告诉我INVALID_HANDLE VALUE
你能解释一下如何解决这个问题吗? 感谢
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;
};
班级方法:
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 title
SetConsoleTitle("Console");
this->hwnd = GetConsoleWindow();
//
//// get handles
this->hin = GetStdHandle(STD_OUTPUT_HANDLE);
this->hout = GetStdHandle(STD_OUTPUT_HANDLE);
return;}
主要功能
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"
}
答案 0 :(得分:1)
我不明白为什么你要弄乱std::cout
et al。如果您将stdout
,stderr
和stdin
重定向到控制台,则可以致电std::ios::sync_with_stdio()
以确保std::cout
,std::cerr
和{{1一切顺利。 E.g:
std::cin
这是一篇很棒的文章(有来源),explains一切。
答案 1 :(得分:0)
您似乎用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() );
即使您的操作系统支持此功能,现在还有两个独立的I / O缓冲区试图控制该文件。如果您尝试同时使用它们,则会导致输出乱码。
将cout
和cerr
发送到不同的文件,或对两者使用相同的filebuf
。
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
我认为这仍然有点不稳定,但它应该得到标准的支持。
答案 2 :(得分:0)
为什么不将您的应用设为控制台应用?您仍然可以从控制台应用程序创建窗口,但这意味着总会有一个控制台,并且始终是标准的输入和输出流。
答案 3 :(得分:0)
麻烦在于使用cin,cout句柄关闭或释放后。 GetLastError表示代码6(ERROR_INVALID_HANDLE)
我试过打开CONOUT $一次就像你说的那样,尝试打开CONERR $而不是CONOUT $两次,也许通过CloseHandle手动关闭CONOUT $ handle并再次使用GetStdHandle(STD_OUTPUT_HANDLE)或CreateFile打开它。
在所有情况下,cout都不会打印任何内容。只有在使用cerr时才会写入剩余的所有内容。