Reputation: 1286
I have the following fragment in my WinMain and I am launching this GUI app from the console. I want to redirect output to the console from which my app was launched.I am getting the "The handle is invalid." error after GetStdHandle().
However, if I use AllocConsole instead of AttachConsole, it works fine. In addition, if I use STD_ERROR_HANDLE instead of STD_OUTPUTHANDLE then fprintf(stderr, "errror") works fine.
I saw a blog entry which had the same problem but no solution. I am using vc 2010 compiler on 64 bit windows 7.
Thanks!
bConsole = AttachConsole(ATTACH_PARENT_PROCESS) != FALSE;
if (bConsole)
{
int fd = 0;
long lStdOut;
lStdOut = (long)GetStdHandle(STD_OUTPUT_HANDLE);
fd = _open_osfhandle(lStdOut, _O_TEXT);
if (fd > 0)
{
*stdout = *_fdopen(fd, "w");
setvbuf(stdout, NULL, _IONBF, 0 );
}
}
printf("Test!!!!!!!!!!!!");
Upvotes: 2
Views: 11310
Reputation: 4225
To redirect output to Console use the following code:
AllocConsole();
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
then you can write to the Console using WriteFile().
WriteFile(
hConsole,
L"this is a debug line\n",
21, // string length
NULL, // bytes written
NULL);
Upvotes: 0
Reputation: 35613
A Windows Subsystem process (i.e. one with WinMain
) will not have a STDOUT, STDERR or STDIN, unless it was specifically given one on launch. The assumption is that since it is a windows program you are interacting with it via Windows.
I.e. GetStdHandle is not returning a handle to STDOUT because you haven't got a STDOUT.
To give it one, launch it thus:
winprog.exe > output.txt 2>&1
If launched in that way, it will have both a STDOUT and STDERR, which will both go into the named file.
As pointed out by other users already, AttachConsole will give you a console (nearest unix/linux equivalent is a TTY) but it will not give you a STDOUT. If you want one you will have to set it as a separate step. If you want it to be the console, you can have that too.
On the other hand a Console subsystem program (one with main
) will by default have a STDIN, STDOUT and STDERR all set to the Console. You can detach the process from the console, and close them if you want.
Upvotes: 6
Reputation: 283634
AttachConsole
does associate your process with a console, but stdout
has already been opened (and connected to the old handle, whatever it was).
Overwriting stdout
directly is a terrible idea. Instead, you must freopen("CONOUT$", "w", stdout);
to get stdout
going to the console.
But there are a lot of other little details. Have a look at my question Where do writes to stdout go when launched from a cygwin shell, no redirection which covers your problem in the question, then asks a question about some corner cases. Finally there's a code sample which incorporates everything.
Upvotes: 7
Reputation: 612934
I added the following code into the default Visual Studio C++ GUI project, right at the start of WinMain
.
if (AttachConsole(ATTACH_PARENT_PROCESS))
{
if (GetStdHandle(STD_OUTPUT_HANDLE) == INVALID_HANDLE_VALUE)
MessageBox(0, L"Invalid Handle", NULL, 0);
else
MessageBox(0, L"Valid Handle", NULL, 0);
}
When I run the GUI program from the debugger, or from Explorer, no message box shows. In other words we can't attach a console. When I run from cmd I see the "Valid Handle" message.
I conclude that there is in fact no problem with this basic approach, but that something that you are not showing us is causing the problem.
Upvotes: 2
Reputation: 5054
I think your problem is here:
long lStdOut;
lStdOut = (long)GetStdHandle(STD_OUTPUT_HANDLE);
fd = _open_osfhandle(lStdOut, _O_TEXT);
I'm not very good with Win32 API, but I think handles have their own HANDLE
types, which are essentially pointers I think, and 64-bit on Win64. long
type in Win64 is though still 32-bit for some reason.
This is the declaration from MSDN:
HANDLE WINAPI GetStdHandle(
__in DWORD nStdHandle
);
Declaration for _open_osfhandle:
int _open_osfhandle (
intptr_t osfhandle,
int flags
);
Upvotes: 0