Jump to content
  • Advertisement
Sign in to follow this  
CableGuy

Redirecting console output

This topic is 3323 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, As the title says I'm trying to redirect console output under Windows. I've embedded Lua in my application and now I want to redirect output from the lua script to a TextBox. I couldn't find much on the internet except someone mentioning creating a pipe and then using SetStdHandle to redirect output to this pipe and then using ReadFile on this pipe to get the output but that doesn't seem to work. The text still gets sent to the console and causing ReadFile to block my application:
HANDLE rd,wr;
if (!CreatePipe(&rd,&wr,NULL,0))
	cout << "Error creating pipe.\n";
HANDLE old=GetStdHandle(STD_OUTPUT_HANDLE);
if (!SetStdHandle(STD_OUTPUT_HANDLE,wr))
	cout << "Error setting std handle.\n";
std::cout << "yo!";	
char buf[100];
while (true)
{
	DWORD readBytes=0;
	if (!ReadFile(rd,buf,1,&readBytes,0))
		break;
	if (readBytes>0)
	{			
		string str;
		for (DWORD i=0;i<readBytes;i++)
			str+=buf;
		MessageBoxA(0,str.c_str(),"",0);
	}
	else
		break;
}
SetStdHandle(STD_OUTPUT_HANDLE,old);

Any suggestions/snippets of code/links are welcomed.

Share this post


Link to post
Share on other sites
Advertisement
Thanks but these examples use the same code of spawning a new process(from another executable) and capturing its IO by setting the new handlers in its creation parameters. What I'm trying to do is redirect the console IO for the current process. I've found some code and was able to get it working but when I switched to a non console application it stopped working. I hope what I'm trying to achieve here is possible cause I haven't seen any solution to this yet.

Share this post


Link to post
Share on other sites
I modified this thread's solution for generating a console in a Win32 application.


#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <io.h>
#include <fcntl.h>

void RedirectConsole(HANDLE hPipe)
{
int hConHandle = 0;
HANDLE lStdHandle = 0;
FILE *fp = 0 ;

// redirect unbuffered STDOUT to the Pipe
lStdHandle = hPipe;
hConHandle = _open_osfhandle(PtrToUlong(lStdHandle), _O_TEXT);
fp = _fdopen(hConHandle, "w");
*stdout = *fp;
setvbuf(stdout, NULL, _IONBF, 0);
}

int main(int argc, char * argv[])
{
HANDLE rd,wr;
if (!CreatePipe(&rd,&wr,NULL,0))
std::cout << "Error creating pipe.\n";
RedirectConsole(wr);
std::cout << "cout\n";
printf("printf\n");
char buf[100];
while (true)
{
DWORD readBytes=0;
if (!ReadFile(rd, buf, 99, &readBytes, 0))
break;
buf[99] = 0;
if (readBytes>0)
{
std::string str;
for (DWORD i=0;i<readBytes;i++)
str+=buf;
MessageBoxA(0,str.c_str(),"",0);
}
else
break;
}
}



For the sake of not making you click through a dozen MessageBox's either, I changed the read to the max buffer size rather than one at a time [wink]

Share this post


Link to post
Share on other sites
Thanks it works. Using cout and printf works like a charm but still I can't capture output from a Lua script. If I replace the printf to be luaL_dostring(luaState,"print(\"test\")") there is no messagebox. Also I've tested running my application from the command prompt with > 1.txt and the text file is filled with the correct output so the print command in lua outputs to stdout.

[Edited by - CableGuy on April 18, 2009 4:05:34 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by CableGuy
Thanks it works. Using cout and printf works like a charm but still I can't capture output from a Lua script. If I replace the printf to be luaL_dostring(luaState,"print(\"test\")") there is no messagebox.


I think you have a problem in your code. I made a simple Lua test and it works fine for me.


#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include <string>
#include <iostream>

extern "C"
{
#include "lua/lua.h"
#include "lua/lualib.h"
#include "lua/lauxlib.h"
}

void RedirectConsole(HANDLE hPipe)
{
int hConHandle = 0;
HANDLE lStdHandle = 0;
FILE *fp = 0 ;

// redirect unbuffered STDOUT to the console
lStdHandle = hPipe;
hConHandle = _open_osfhandle(PtrToUlong(lStdHandle), _O_TEXT);
fp = _fdopen(hConHandle, "w");
*stdout = *fp;
setvbuf(stdout, NULL, _IONBF, 0);
}

int main(int argc, char** argv)
{
lua_State * L = lua_open();
luaL_openlibs(L);

HANDLE rd,wr;
if (!CreatePipe(&rd,&wr,NULL,0))
std::cout << "Error creating pipe.\n";
RedirectConsole(wr);

luaL_dostring(L, "print(\"test\")");

char buf[100];
while (true)
{
DWORD readBytes=0;
if (!ReadFile(rd, buf, 99, &readBytes, 0))
break;
buf[99] = 0;
if (readBytes>0)
{
std::string str;
for (DWORD i=0;i<readBytes;i++)
str+=buf;
MessageBoxA(0,str.c_str(),"",0);
break;
}
else
break;
}

lua_close(L);

return EXIT_SUCCESS;
}




Does your Lua state have I/O functions enabled for it? That's the only thing off the top of my head right now.

Share this post


Link to post
Share on other sites
Weird your code doesn't work for me...

EDIT: For some weird reason if I use Lua as a DLL it doesn't work but if I use it as a static lib it works...

[Edited by - CableGuy on April 18, 2009 5:29:03 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by CableGuy
Weird your code doesn't work for me...

EDIT: For some weird reason if I use Lua as a DLL it doesn't work but if I use it as a static lib it works...


Really weird. I'm using Lua via a static Library, not a DLL. I've got version: lua5_1_4_Win32_vc8_lib.

Attached is a complete project with my Lua version for you to try. Although if you have set Visual Studio settings to pull from specific folders via Tools menu, you will want to change that first so it does not use your .lib files and instead uses mine.

Download: CableGuy

Share this post


Link to post
Share on other sites
Quote:
Original post by CableGuy
Weird your code doesn't work for me...

EDIT: For some weird reason if I use Lua as a DLL it doesn't work but if I use it as a static lib it works...


If you app and the lua dll aren't linked to the same dll version of the CRT (Project Properties->C/C++->Code Generation->Runtime Library->Multi-Threaded (Debug) DLL) then they'll each have a different stdout "file". Any changes you make to it in your code, like using the RedirectConsole function, will only affect your copy.

Oh and
Quote:

void RedirectConsole(HANDLE hPipe)
{
..
// redirect unbuffered STDOUT to the Pipe
lStdHandle = hPipe;
// PtrToUlong chops the handle in half on 64-bit windows
hConHandle = _open_osfhandle(reinterpret_cast<intptr_t>(lStdHandle), _O_TEXT);
}


The stdout assignment also leaks everything to do with the original, but I'm not sure if doing fclose(stdout); before the assignment is kosher.

Share this post


Link to post
Share on other sites
Thank you both got it working now, using a static lib.
@adeyblue: A bit off topic: So lets say I have three dlls : A,B,C. A and B are both linked against C. When I have an executable that links against A,B only one instance of C is mapped to it?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!