If I have a native C++ windows program (i.e. the entry point is WinMain) how do I view output from console functions like std::cout?
Check out Adding Console I/O to a Win32 GUI App. This may help you do what you want.
If you don't have, or can't modify the code, try the suggestions found here to redirect console output to a file.
Edit: bit of thread necromancy here. I first answered this 9ish years ago, in the early days of SO, before the (good) policy of non-link-only answers came into effect. I'll repost the code from the original article in the hope to atone for my past sins.
guicon.cpp -- A console redirection function
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <fstream>
#ifndef _USE_OLD_IOSTREAMS
using namespace std;
#endif
// maximum mumber of lines the output console should have
static const WORD MAX_CONSOLE_LINES = 500;
#ifdef _DEBUG
void RedirectIOToConsole()
{
int hConHandle;
long lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// allocate a console for this app
AllocConsole();
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
// redirect unbuffered STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );
// redirect unbuffered STDIN to the console
lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "r" );
*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );
// redirect unbuffered STDERR to the console
lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stderr = *fp;
setvbuf( stderr, NULL, _IONBF, 0 );
// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
// point to console as well
ios::sync_with_stdio();
}
#endif
//End of File
guicon.h -- Interface to console redirection function
#ifndef __GUICON_H__
#define __GUICON_H__
#ifdef _DEBUG
void RedirectIOToConsole();
#endif
#endif
// End of File
test.cpp -- Demonstrating console redirection
#include <windows.h>
#include <iostream>
#include <fstream>
#include <conio.h>
#include <stdio.h>
#ifndef _USE_OLD_OSTREAMS
using namespace std;
#endif
#include "guicon.h"
#include <crtdbg.h>
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
#ifdef _DEBUG
RedirectIOToConsole();
#endif
int iVar;
// test stdio
fprintf(stdout, "Test output to stdout\n");
fprintf(stderr, "Test output to stderr\n");
fprintf(stdout, "Enter an integer to test stdin: ");
scanf("%d", &iVar);
printf("You entered %d\n", iVar);
//test iostreams
cout << "Test output to cout" << endl;
cerr << "Test output to cerr" << endl;
clog << "Test output to clog" << endl;
cout << "Enter an integer to test cin: ";
cin >> iVar;
cout << "You entered " << iVar << endl;
#ifndef _USE_OLD_IOSTREAMS
// test wide iostreams
wcout << L"Test output to wcout" << endl;
wcerr << L"Test output to wcerr" << endl;
wclog << L"Test output to wclog" << endl;
wcout << L"Enter an integer to test wcin: ";
wcin >> iVar;
wcout << L"You entered " << iVar << endl;
#endif
// test CrtDbg output
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR);
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR);
_RPT0(_CRT_WARN, "This is testing _CRT_WARN output\n");
_RPT0(_CRT_ERROR, "This is testing _CRT_ERROR output\n");
_ASSERT( 0 && "testing _ASSERT" );
_ASSERTE( 0 && "testing _ASSERTE" );
Sleep(2000);
return 0;
}
//End of File
The problem some of the other answers is that they unnecessarily create new FILE instances which are then leaked and can cause debug assertions in the CRT cleanup code.
freopen_s is all that is really needed:
FILE* fp = nullptr;
freopen_s(&fp, "CONIN$", "r", stdin);
freopen_s(&fp, "CONOUT$", "w", stdout);
freopen_s(&fp, "CONOUT$", "w", stderr);
You'll probably want to do a little error checking and cleanup as well. Below is the complete solution that I currently use.
Redirecting Console Standard IO:
bool RedirectConsoleIO()
{
bool result = true;
FILE* fp;
// Redirect STDIN if the console has an input handle
if (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)
if (freopen_s(&fp, "CONIN$", "r", stdin) != 0)
result = false;
else
setvbuf(stdin, NULL, _IONBF, 0);
// Redirect STDOUT if the console has an output handle
if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE)
if (freopen_s(&fp, "CONOUT$", "w", stdout) != 0)
result = false;
else
setvbuf(stdout, NULL, _IONBF, 0);
// Redirect STDERR if the console has an error handle
if (GetStdHandle(STD_ERROR_HANDLE) != INVALID_HANDLE_VALUE)
if (freopen_s(&fp, "CONOUT$", "w", stderr) != 0)
result = false;
else
setvbuf(stderr, NULL, _IONBF, 0);
// Make C++ standard streams point to console as well.
ios::sync_with_stdio(true);
// Clear the error state for each of the C++ standard streams.
std::wcout.clear();
std::cout.clear();
std::wcerr.clear();
std::cerr.clear();
std::wcin.clear();
std::cin.clear();
return result;
}
Releasing a Console:
bool ReleaseConsole()
{
bool result = true;
FILE* fp;
// Just to be safe, redirect standard IO to NUL before releasing.
// Redirect STDIN to NUL
if (freopen_s(&fp, "NUL:", "r", stdin) != 0)
result = false;
else
setvbuf(stdin, NULL, _IONBF, 0);
// Redirect STDOUT to NUL
if (freopen_s(&fp, "NUL:", "w", stdout) != 0)
result = false;
else
setvbuf(stdout, NULL, _IONBF, 0);
// Redirect STDERR to NUL
if (freopen_s(&fp, "NUL:", "w", stderr) != 0)
result = false;
else
setvbuf(stderr, NULL, _IONBF, 0);
// Detach from console
if (!FreeConsole())
result = false;
return result;
}
Resizing Console Buffer:
void AdjustConsoleBuffer(int16_t minLength)
{
// Set the screen buffer to be big enough to scroll some text
CONSOLE_SCREEN_BUFFER_INFO conInfo;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &conInfo);
if (conInfo.dwSize.Y < minLength)
conInfo.dwSize.Y = minLength;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), conInfo.dwSize);
}
Allocating a New Console:
bool CreateNewConsole(int16_t minLength)
{
bool result = false;
// Release any current console and redirect IO to NUL
ReleaseConsole();
// Attempt to create new console
if (AllocConsole())
{
AdjustConsoleBuffer(minLength);
result = RedirectConsoleIO();
}
return result;
}
Attaching to Parent's Console:
bool AttachParentConsole(int16_t minLength)
{
bool result = false;
// Release any current console and redirect IO to NUL
ReleaseConsole();
// Attempt to attach to parent process's console
if (AttachConsole(ATTACH_PARENT_PROCESS))
{
AdjustConsoleBuffer(minLength);
result = RedirectConsoleIO();
}
return result;
}
Calling from WinMain:
Link with /SUBSYSTEM:Windows
int APIENTRY WinMain(
HINSTANCE /*hInstance*/,
HINSTANCE /*hPrevInstance*/,
LPTSTR /*lpCmdLine*/,
int /*cmdShow*/)
{
if (CreateNewConsole(1024))
{
int i;
// test stdio
fprintf(stdout, "Test output to stdout\n");
fprintf(stderr, "Test output to stderr\n");
fprintf(stdout, "Enter an integer to test stdin: ");
scanf("%d", &i);
printf("You entered %d\n", i);
// test iostreams
std::cout << "Test output to std::cout" << std::endl;
std::cerr << "Test output to std::cerr" << std::endl;
std::clog << "Test output to std::clog" << std::endl;
std::cout << "Enter an integer to test std::cin: ";
std::cin >> i;
std::cout << "You entered " << i << std::endl;
std::cout << endl << "Press any key to continue..." << endl;
_getch();
ReleaseConsole();
}
return 0;
};
You can also reopen the cout and cerr streams to output to a file as well. The following should work for this:
#include <iostream>
#include <fstream>
int main ()
{
std::ofstream file;
file.open ("cout.txt");
std::streambuf* sbuf = std::cout.rdbuf();
std::cout.rdbuf(file.rdbuf());
//cout is now pointing to a file
return 0;
}
Actually there is a much simpler solution than any proposed so far. Your Windows program will have a WinMain function so just add this "dummy" main function as well
int main()
{
return WinMain(GetModuleHandle(NULL), NULL, GetCommandLineA(), SW_SHOWNORMAL);
}
You can now compile using MSVC like this
cl /nologo /c /EHsc myprog.c
link /nologo /out:myprog.exe /subsystem:console myprog.obj user32.lib gdi32.lib
(you may need to add more library links)
When you run the program any printf will be written to the command prompt.
If you are using gcc (mingw) to compile for Windows you don't need a dummy main function, just do
gcc -o myprog.exe myprog.c -luser32 -lgdi32
(ie avoid using the -mwindows flag which will prevent writing to a console. That flag will be useful when you create the final GUI release) Again you may need to specify more libraries if using more windows features)
If you are sending the output of your program to a file or pipe, e.g.
myprogram.exe > file.txt
myprogram.exe | anotherprogram.exe
or you are invoking your program from another program and capturing its output through a pipe, then you don't need to change anything. It will just work, even if the entry point is WinMain.
However, if you are running your program in a console or in Visual Studio, then the output will not appear in the console or in the Output window of Visual Studio. If you want to see the output "live", then try one of the other answers.
Basically, this means that standard output works just like with console applications, but it isn't connected to a console in which you are running your application, and there seems to be no easy way to do that (all the other solutions presented here connect the output to a new console window that will pop up when you run your application, even from another console).
Using a combination of luke's answer and Roger's answer here worked for me in my Windows Desktop Application project.
void RedirectIOToConsole() {
//Create a console for this application
AllocConsole();
// Get STDOUT handle
HANDLE ConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
int SystemOutput = _open_osfhandle(intptr_t(ConsoleOutput), _O_TEXT);
FILE *COutputHandle = _fdopen(SystemOutput, "w");
// Get STDERR handle
HANDLE ConsoleError = GetStdHandle(STD_ERROR_HANDLE);
int SystemError = _open_osfhandle(intptr_t(ConsoleError), _O_TEXT);
FILE *CErrorHandle = _fdopen(SystemError, "w");
// Get STDIN handle
HANDLE ConsoleInput = GetStdHandle(STD_INPUT_HANDLE);
int SystemInput = _open_osfhandle(intptr_t(ConsoleInput), _O_TEXT);
FILE *CInputHandle = _fdopen(SystemInput, "r");
//make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog point to console as well
ios::sync_with_stdio(true);
// Redirect the CRT standard input, output, and error handles to the console
freopen_s(&CInputHandle, "CONIN$", "r", stdin);
freopen_s(&COutputHandle, "CONOUT$", "w", stdout);
freopen_s(&CErrorHandle, "CONOUT$", "w", stderr);
//Clear the error state for each of the C++ standard stream objects. We need to do this, as
//attempts to access the standard streams before they refer to a valid target will cause the
//iostream objects to enter an error state. In versions of Visual Studio after 2005, this seems
//to always occur during startup regardless of whether anything has been read from or written to
//the console or not.
std::wcout.clear();
std::cout.clear();
std::wcerr.clear();
std::cerr.clear();
std::wcin.clear();
std::cin.clear();
}
creating a pipe, execute the program console CreateProcess() and read with ReadFile() or writes in console WriteFile()
HANDLE hRead ; // ConsoleStdInput
HANDLE hWrite; // ConsoleStdOutput and ConsoleStdError
STARTUPINFO stiConsole;
SECURITY_ATTRIBUTES segConsole;
PROCESS_INFORMATION priConsole;
segConsole.nLength = sizeof(segConsole);
segConsole.lpSecurityDescriptor = NULL;
segConsole.bInheritHandle = TRUE;
if(CreatePipe(&hRead,&hWrite,&segConsole,0) )
{
FillMemory(&stiConsole,sizeof(stiConsole),0);
stiConsole.cb = sizeof(stiConsole);
GetStartupInfo(&stiConsole);
stiConsole.hStdOutput = hWrite;
stiConsole.hStdError = hWrite;
stiConsole.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
stiConsole.wShowWindow = SW_HIDE; // execute hide
if(CreateProcess(NULL, "c:\\teste.exe",NULL,NULL,TRUE,NULL,
NULL,NULL,&stiConsole,&priConsole) == TRUE)
{
//readfile and/or writefile
}
}
Go to Project>Project Properties>Linker>System and in the right pane, set SubSystems option to Console(/SUBSYSTEM:CONSOLE)
Then compile your program and run it from console to see whether you command prompt shows your outputs or not.
Don't quote me on this, but the Win32 console API might be what you're looking for. If you're just doing this for debugging purposes, however, you might be more interested in running DebugView and calling the DbgPrint function.
This of course assumes its your application you want sending console output, not reading it from another application. In that case, pipes might be your friend.
As mentioned there and there the easiest solution is to use your Project Property Pages to switch back and forth between CONSOLE and WINDOWS SubSytems to enable or disable console output at will.
Your program will just need main and WinMain entry points to make sure both configuration are compiling.
The main function simply calling WinMain as shown below for instance:
int main()
{
cout << "Output standard\n";
cerr << "Output error\n";
return WinMain(GetModuleHandle(NULL), NULL, GetCommandLineA(), SW_SHOWNORMAL);
}
Since there's no console window, this is impossible difficult. (Learn something new every day - I never knew about the console functions!)
Is it possible for you to replace your output calls? I will often use TRACE or OutputDebugString to send information to the Visual Studio output window.
Related
I'm creating a Windows service, which cannot have an associated console. Therefore I want to redirect stdout and stderr to a (the same) file. Here is what I discovered so far:
Redirecting cout and cerr in C++ can be done by changing the buffers, but this does not affect C I/O like puts or Windows I/O handles.
Hence we can use freopen to reopen stdout or stderr as a file like here, but we cannot specify the same file twice.
To still use the same file for both we can redirect stderr to stdout using dup2 like here.
So far so good, and when we run this code with /SUBSYSTEM:CONSOLE (project properties → Linker → System) everything works fine:
#include <Windows.h>
#include <io.h>
#include <fcntl.h>
#include <cstdio>
#include <iostream>
void doit()
{
FILE *stream;
if (_wfreopen_s(&stream, L"log.log", L"w", stdout)) __debugbreak();
// Also works as service when uncommenting this line: if (_wfreopen_s(&stream, L"log2.log", L"w", stderr)) __debugbreak();
if (_dup2(_fileno(stdout), _fileno(stderr)))
{
const auto err /*EBADF if service; hover over in debugger*/ = errno;
__debugbreak();
}
// Seemingly can be left out for console applications
if (!SetStdHandle(STD_OUTPUT_HANDLE, reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(stdout))))) __debugbreak();
if (!SetStdHandle(STD_ERROR_HANDLE, reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(stderr))))) __debugbreak();
if (_setmode(_fileno(stdout), _O_WTEXT) == -1) __debugbreak();
if (_setmode(_fileno(stderr), _O_WTEXT) == -1) __debugbreak();
std::wcout << L"1☺a" << std::endl;
std::wcerr << L"1☺b" << std::endl;
_putws(L"2☺a");
fflush(stdout);
fputws(L"2☺b\n", stderr);
fflush(stderr);
const std::wstring a3(L"3☺a\n"), b3(L"3☺b\n");
if (!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), a3.c_str(), a3.size() * sizeof(wchar_t), nullptr, nullptr))
__debugbreak();
if (!WriteFile(GetStdHandle(STD_ERROR_HANDLE), b3.c_str(), b3.size() * sizeof(wchar_t), nullptr, nullptr))
__debugbreak();
}
int main() { doit(); }
int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) { return doit(), 0; }
This nicely writes the following text to log.log:
1☺a
1☺b
2☺a
2☺b
3☺a
3☺b
(Of course we want emoji, so we need some sort of unicode. In this case we use wide characters, which means we need to use setmode or else everything will mess up. You may also need to save the cpp file in an encoding that MSVC understands, e.g. UTF-8 with signature.)
But now back to the original problem: doing this as a service without console, or, equivalent but easier to debug, a GUI app (/SUBSYSTEM:WINDOWS).
The problem is that in this case dup2 fails because fileno(stderr) is not a valid file descriptor, because the app initially has no associated streams. As mentioned here, fileno(stderr) == -2 in this case.
Note that when we first open stderr as another file using freopen, everything works fine, but we created a dummy empty file.
So now my question is: what is the best way to redirect both stdout and stderr to the same file in an application which initially has no streams?
Just to recap: the problem is that when stdout or stderr is not associated with an output stream, fileno returns -2, so we cannot pass it to dup2.
(I do not want to change the code used for the actual printing, because that might mean that some output produced by external functions will not be redirected.)
Here's an example of a program that creates a file for writing and then uses CreateProcess and setting stdout and stderr for the process to the HANDLE of the created file. This example just starts itself with a dummy argument to make it write a lot of things to stdout and stderr that will be written to output.txt.
// RedirectStd.cpp
#include <iostream>
#include <string_view>
#include <vector>
#include <Windows.h>
struct SecAttrs_t : public SECURITY_ATTRIBUTES {
SecAttrs_t() : SECURITY_ATTRIBUTES{ 0 } {
nLength = sizeof(SECURITY_ATTRIBUTES);
bInheritHandle = TRUE;
}
operator SECURITY_ATTRIBUTES* () { return this; }
};
struct StartupInfo_t : public STARTUPINFO {
StartupInfo_t(HANDLE output) : STARTUPINFO{ 0 } {
cb = sizeof(STARTUPINFO);
dwFlags = STARTF_USESTDHANDLES;
hStdOutput = output;
hStdError = output;
}
operator STARTUPINFO* () { return this; }
};
int cppmain(const std::string_view program, std::vector<std::string_view> args) {
if (args.size() == 0) {
// no arguments, create a file and start a new process
SecAttrs_t sa;
HANDLE hFile = CreateFile(L"output.txt",
GENERIC_WRITE,
FILE_SHARE_READ,
sa, // lpSecurityAttributes
CREATE_ALWAYS, // dwCreationDisposition
FILE_ATTRIBUTE_NORMAL, // dwFlagsAndAttributes
NULL // dwFlagsAndAttributesparameter
);
if (hFile == INVALID_HANDLE_VALUE) return 1;
StartupInfo_t su(hFile); // set output handles to hFile
PROCESS_INFORMATION pi;
std::wstring commandline = L"RedirectStd.exe dummy";
BOOL bCreated = CreateProcess(
NULL,
commandline.data(),
NULL, // lpProcessAttributes
NULL, // lpThreadAttributes
TRUE, // bInheritHandles
0, // dwCreationFlags
NULL, // lpEnvironment
NULL, // lpCurrentDirectory
su, // lpStartupInfo
&pi
);
if (bCreated == 0) return 2;
CloseHandle(pi.hThread); // no need for this
WaitForSingleObject(pi.hProcess, INFINITE); // wait for the process to finish
CloseHandle(pi.hProcess);
CloseHandle(hFile);
}
else {
// called with an argument, output stuff to stdout and stderr
for (int i = 0; i < 1024; ++i) {
std::cout << "stdout\n";
std::cerr << "stderr\n";
}
}
return 0;
}
int main(int argc, char* argv[]) {
return cppmain(argv[0], { argv + 1, argv + argc });
}
I found a solution that works and does not create a temporary file log2.log. Instead of this file, we can open NUL (Windows's /dev/null), so the code becomes:
FILE *stream;
if (_wfreopen_s(&stream, L"log.log", L"w", stdout)) __debugbreak();
if (freopen_s(&stream, "NUL", "w", stderr)) __debugbreak();
if (_dup2(_fileno(stdout), _fileno(stderr))) __debugbreak();
if (!SetStdHandle(STD_OUTPUT_HANDLE, reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(stdout))))) __debugbreak();
if (!SetStdHandle(STD_ERROR_HANDLE, reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(stderr))))) __debugbreak();
if (_setmode(_fileno(stdout), _O_WTEXT) == -1) __debugbreak();
if (_setmode(_fileno(stderr), _O_WTEXT) == -1) __debugbreak();
This makes sure that _fileno(stderr) is not -2 anymore so we can use dup2.
There might be a more elegant solution (not sure), but this works and does not create a dummy empty file (also not one named NUL).
I'm writing a class to display a custom console from inside the application. I'm also using glog to log messages to a file and at the same time to stderr. How can I have my console class listen to stderr?
I thought of making a custom fstream and the doing something like:
CustomStream cs;
auto original_buf = std::cerr.rdbuf(cs.rdbuf());
and having calls to the stream operator << sent to the console class.
Or subclassing directly from std::filebuf and calling:
CustomFilebuf fb;
auto original_buf = std::cerr.rdbuf(&fb);
Is this the right way to do it? I searched for some sample code but couldn't find very much.
Edit1: I tried using stream tee, but glog logs with stderr and not std::cerr, so I wasn't able to grab any data.
I am uncertain if this is relevant to your question, but...
ISO C99 says in 7.19.5.3, paragraph 6:
When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function [...], and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
Also some say reading from stderr is "undefined behavior"...
Though you can read from stderr, as long as you flush before reading:
fwrite("x", 1, 1, stderr);
fflush(stderr);
fgetc(stderr);
Also take a look at How do I read stdout/stderr output of a child process correctly?
For anyone who would like to redirect stdout to a console Window in a Win32 app there is
AllocConsole.
I even created a simple (trivial) function to redirect stdout to the console Window:
#include <fstream>
#include <io.h>
#include <fcntl.h>
#define cMaxConsoleLines 500
void ReadyConsole() {
short int hConHandle;
long lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// Allocate a console for the program
AllocConsole();
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
coninfo.dwSize.Y = cMaxConsoleLines; // The max number of lines for the console!
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
// Redirect STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "w"); // Writing to the console
*stdout = *fp;
setvbuf(stdout, NULL, _IONBF, 0);
// -------------------------------
// Redirect STDIN to the console
lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "r"); // Reading from the console
*stdin = *fp;
setvbuf(stdin, NULL, _IONBF, 0);
// ------------------------------
// Redirect STDERR to the console
lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "w"); // STDERR writing to the console!
*stderr = *fp;
setvbuf(stderr, NULL, _IONBF, 0);
// ------------------------------
// Point the console to STDIO
std::ios::sync_with_stdio();
}
If you would like the console to be for Debug only, make sure to include <crtdbg.h>, which defines whether the app is in debug mode (for VC++), then, for example you could add:
#ifdef _DEBUG
// The file with the ReadyConsole function
#include <DebugStuff.h>
#endif
and to use it
#ifdef _DEBUG
ReadyConsole(); // Ready the console for debugging
#endif
#ifdef _DEBUG
fprintf(stdout, "Position, Line 1, DEBUG-INFO-HERE");
cout << "COUT is working!"; // NOTE, for cout, you will need <iostream>
#endif
Here is an additional little function (it logs the message to both stderr and stderr.log file)
void StdErr(char* Error) {
fprintf(stderr, Error);
FILE* FP = fopen("stderr.log", "a");
fputs(Error, FP);
fclose(FP);
}
I am using _popen to start a process to run a command and gather the output
This is my c++ code:
bool exec(string &cmd, string &result)
{
result = "";
FILE* pipe = _popen(cmd.c_str(), "rt");
if (!pipe)
return(false);
char buffer[128];
while(!feof(pipe))
{
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
_pclose(pipe);
return(true);
}
Is there any way of doing this without a console window opening (as it currently does at the _popen statement)?
On Windows, CreateProcess with a STARTUPINFO structure that has dwFlags to include STARTF_USESSHOWWINDOW. Then setting STARTUPINFO.dwFlags to SW_HIDE will cause the console window to be hidden when triggered. Example code (which may be poorly formatted, and contains a mix of C++ and WinAPI):
#include <windows.h>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
void printError(DWORD);
int main()
{
STARTUPINFOA si = {0};
PROCESS_INFORMATION pi = { 0 };
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
BOOL result = ::CreateProcessA("c:/windows/system32/notepad.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if(result == 0) {
DWORD error = ::GetLastError();
printError(error);
std::string dummy;
std::getline(std::cin, dummy);
return error;
}
LPDWORD retval = new DWORD[1];
::GetExitCodeProcess(pi.hProcess, retval);
cout << "Retval: " << retval[0] << endl;
delete[] retval;
cout << "Press enter to continue..." << endl;
std::string dummy;
std::getline(std::cin, dummy);
return 0;
}
void printError(DWORD error) {
LPTSTR lpMsgBuf = nullptr;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
cout << reinterpret_cast<char*>(lpMsgBuf) << endl;
LocalFree(lpMsgBuf);
}
As far as I know, you can't1: you are starting a console application (cmd.exe, that will run the specified command), and Windows always creates a console window when starting a console application.
although, you can hide the window after the process started, or even create it hidden if you pass the appropriate flags to CreateProcess; problem is, _popen do not pass these flags, so you have to use the Win32 APIs instead of _popen to create your pipe.
[Final Edit]
a similar SO question merges everything said above and gets you your output
C++ popen command without console
[Edited again]
erk. sorry I got excited about spawning processes. I reread your q. and apart from the extra window you're actually trying to get the processes's stdout/stderr. I'd just like to add that for that purpose, all my suggestions are sadly irrelevant. but I'll leave them here for reference.
[Edited]
For no good specific reason (except that "open" works for both windows and macs), I use ShellExecute for spawning processes rather than CreateProcess. I'll research that later..but here is my StartProcess function.
Hidden or Minimized seem to produce the same result. the cmd window does come into being but it is minimized and doesn't ever pop up on the desktop which might be your primary goal.
#if defined(PLATFORM_WIN32)
#include <Windows.h>
#include <shellapi.h>
#elif defined(PLATFORM_OSX)
#include <sys/param.h>
#endif
namespace LGSysUtils
{
// -----------------------------------------------------------------------
// pWindow : {Optional} - can be NULL
// pOperation : "edit", "explore", "find", "open", "print"
// pFile : url, local file to execute
// pParameters : {Optional} - can be NULL otherwise a string of args to pass to pFile
// pDirectory : {Optional} - set cwd for process
// type : kProcessWinNormal, kProcessWinMinimized, kProcessWinMaximized, kProcessHidden
//
bool StartProcess(void* pWindow, const char* pOperation, const char* pFile, const char* pParameters, const char* pDirectory, LGSysUtils::eProcessWin type)
{
bool rc = false;
#if defined(PLATFORM_WIN32)
int showCmd;
switch(type)
{
case kProcessWinMaximized:
showCmd = SW_SHOWMAXIMIZED;
break;
case kProcessWinMinimized:
showCmd = SW_SHOWMINIMIZED;
break;
case kProcessHidden:
showCmd = SW_HIDE;
break;
case kProcessWinNormal:
default:
showCmd = SW_NORMAL;
}
int shellRC = (int)ShellExecute(reinterpret_cast<HWND>(pWindow), pOperation,pFile,pParameters,pDirectory,showCmd);
//Returns a value greater than 32 if successful, or an error value that is less than or equal to 32 otherwise.
if( shellRC > 32 )
{
rc = true;
}
#elif defined(PLATFORM_OSX)
char cmd[1024];
sprintf(cmd, "%s %s", pOperation, pFile);
int sysrc = system( cmd );
dbPrintf("sysrc = %d", sysrc);
rc = true;
#endif
return rc;
}
}
[and previously mentioned]
If you are in control of the source code for the application that is launched, you could try adding this to the top of your main.cpp (or whatever you have named it)
// make this process windowless/aka no console window
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
You could also feed those options to the linker directly. The above is easier to play with for different build configurations imho.
I am building a tool that can be both graphical or purely with a command line interface.
It's up to the user to decide with a command line option "--command_line_only". My IDE is Visual Studio 2008.
I can't seem to find the right project property to make sure
standard output prints are displayed when using the command line interface mode
no command line box is opened when using the tool in its graphical mode
Is there a way to do that ? Visual Studio's devenv seems to behave like this, so i am pretty sure it can be done !
EDIT: I seem to have answered your title, but on re reading your question I am not sure this is what you are asking. I leave the answer here as it might be useful to someone searching your title
Yes you can do this but in general visual studies doesn't make it very easy to separate code from gui (particuly from the hello world examples that are very bound). If you want to mix input then you really want to make sure this is done very well from the beginning.
My advice is to start with the command line options. If you are allowed to use boost (for lisencing reasons) then use boost::program_options.
Then once you have got that going you can add the gui on top. Also, I would recommonend using a gui library such as gtk++ as it is cross platform .
This is not an easy thing to do, IIRC. The problem is that on Windows the executable itself has a flag whether it is a GUI application or console application and e.g. cmd.exe behaves differently when executing one or the other. I suggest that you split the core functionality of your application into a library and build separate CLI and GUI front ends.
EDIT: If you really insist, this goes a long way towards the goal. The goto is there for historical reasons, it could be replaced by the if now:
static
bool
usable_handle (HANDLE h)
{
return h && h != INVALID_HANDLE_VALUE;
}
static
bool
try_reopen_std_handle (int dest_handle, DWORD os_handle_num, HANDLE os_handle,
int flags)
{
if (! usable_handle (os_handle))
return false;
int ret = SetStdHandle (os_handle_num, os_handle);
assert (ret);
if (! ret)
return false;
int base_flags = 0;
#if defined (UNICODE)
//base_flags = _O_WTEXT;
#endif
int opened_handle = _open_osfhandle (reinterpret_cast<intptr_t>(os_handle),
flags | base_flags);
assert (opened_handle != -1 && "_open_osfhandle");
if (opened_handle == -1)
return false;
int dupd_handle = _dup2 (opened_handle, dest_handle);
assert (dupd_handle != -1 && "_dup2");
return dupd_handle == 0;
}
static
bool
try_fdopen (FILE * f, int handle, char const * mode)
{
FILE * tmp = _fdopen (handle, mode);
if (tmp && f)
*f = *tmp;
return !! tmp;
}
static
HANDLE
try_dup_os_handle (HANDLE src)
{
if (! usable_handle (src))
return INVALID_HANDLE_VALUE;
HANDLE dest = INVALID_HANDLE_VALUE;
HANDLE const process = GetCurrentProcess ();
if (DuplicateHandle (process, src, process, &dest, 0, TRUE,
DUPLICATE_SAME_ACCESS))
return dest;
else
return INVALID_HANDLE_VALUE;
}
static
void
init_std_io ()
{
// Retrieve inherited standard handles. AttachConsole() will close
// the existing standard handles, so we duplicate them here first
// to keep them alive.
HANDLE os_stdin = try_dup_os_handle (GetStdHandle (STD_INPUT_HANDLE));
HANDLE os_stdout = try_dup_os_handle (GetStdHandle (STD_OUTPUT_HANDLE));
HANDLE os_stderr = try_dup_os_handle (GetStdHandle (STD_ERROR_HANDLE));
// Attach existing console or allocate a new one.
int ret = AttachConsole (ATTACH_PARENT_PROCESS);
if (ret)
OutputDebugString (_T("Attached existing console.\n"));
else
{
ret = AllocConsole ();
if (ret)
OutputDebugString (_T("Allocated new console.\n"));
else
OutputDebugString (_T("Failed to allocate new console.\n"));
assert (ret);
}
// Open a "POSIX" handle for each OS handle and then fdopen() a C stream
// for each such "POSIX" handle.
//
// Only use the standard handle provided by AttachConsole() if the standard
// handle from before AttachConsole() is not usable.
//
// Finally, re-open standard C stream.
if (! usable_handle (os_stdin))
os_stdin = GetStdHandle (STD_INPUT_HANDLE);
ret = try_reopen_std_handle (0, STD_INPUT_HANDLE, os_stdin, _O_RDONLY);
if (! ret)
goto do_stdout;
try_fdopen (stdin, 0, "r");
do_stdout:
if (! usable_handle (os_stdout))
os_stdout = GetStdHandle (STD_OUTPUT_HANDLE);
ret = try_reopen_std_handle (1, STD_OUTPUT_HANDLE, os_stdout, _O_WRONLY);
if (! ret)
goto do_stderr;
try_fdopen (stdout, 1, "w");
do_stderr:
if (! usable_handle (os_stderr))
os_stderr = GetStdHandle (STD_ERROR_HANDLE);
ret = try_reopen_std_handle (2, STD_ERROR_HANDLE, os_stderr, _O_WRONLY);
if (! ret)
goto done_stderr;
try_fdopen (stderr, 2, "w");
done_stderr:;
}
Build the application as a Win32 application (not a console application), and examine the parameters to decide whether or not to use the console window.
The following code is based on this.
To use a console; create a class called CConsoleAttacher. Use it as follows, basically if there are arguments then open a console which will connect to the CMD window if you started from that. Obviously with Win32 applications when you launch the main windows it detaches from the console so this needs to be handled early on before creating app windows (which is what you want to do anyway...)
CConsoleAttacher ca;
if (ca.hasArguments())
{
ca.ConnectToConsole();
}
printf ("Test output \n");
Create a class called CConsoleAttacher.
CConsoleAttacher.cpp
#include "StdAfx.h"
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <fstream>
#include "ConsoleAttacher.h"
#ifndef _USE_OLD_IOSTREAMS
using namespace std;
#endif
static const WORD MAX_CONSOLE_LINES = 500;
CConsoleAttacher::CConsoleAttacher(void)
{
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
}
CConsoleAttacher::~CConsoleAttacher(void)
{
LocalFree(argv);
}
int CConsoleAttacher::getArgumentCount(void)
{
return argc;
}
CString CConsoleAttacher::getArgument(int id)
{
CString arg ;
if (id < argc)
{
arg = argv[id];
}
return arg;
}
bool CConsoleAttacher::hasArguments(void)
{
return argc > 1;
}
void CConsoleAttacher::ConnectToConsole(void)
{
int hConHandle;
HANDLE lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// allocate a console for this app
if (!AttachConsole(ATTACH_PARENT_PROCESS))
{
if (!AllocConsole())
return;
}
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&coninfo);
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),coninfo.dwSize);
// redirect unbuffered STDOUT to the console
lStdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle((intptr_t)lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );
// redirect unbuffered STDIN to the console
lStdHandle = GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle((intptr_t)lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "r" );
*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );
// redirect unbuffered STDERR to the console
lStdHandle = GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle((intptr_t)lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stderr = *fp;
setvbuf( stderr, NULL, _IONBF, 0 );
// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
// point to console as well
ios::sync_with_stdio();
}
CConsoleAttacher.h
#pragma once
class CConsoleAttacher
{
private:
int argc;
wchar_t** argv;
public:
CConsoleAttacher(void);
~CConsoleAttacher(void);
int getArgumentCount(void);
CString CConsoleAttacher::getArgument(int id);
void ConnectToConsole(void);
bool hasArguments(void);
};
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 title
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.