Cout doesn't print anything to costom console on visual 2015

Hello everyone,

The exact same code use to work on microsoft visual studio 2010 and 2013
but after switching into 2015 it suddenly doesn't work:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

#define EXP __declspec(dllexport)  __stdcall
#define EXP2 __declspec(dllexport) *  __stdcall
using namespace std;

void SPGoConsole(int status);
void EXP ttest(int in)
{
	SPGoConsole(1);
	cout << "Hello world!" << endl;
}

void EXP ttest2(int in)
{
}

void SPGoConsole(int status)
{
	if (status == 0)
	{
		FreeConsole();
		return;
	}
	int hConHandle;
	long lStdHandle;
	CONSOLE_SCREEN_BUFFER_INFO coninfo;
	FILE *fp;
	AllocConsole();
	GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
	coninfo.dwSize.Y = 1000;
	coninfo.dwSize.X = 1000;
	SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
	lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
	fp = _fdopen(hConHandle, "w");
	*stdout = *fp;
	setvbuf(stdout, NULL, _IONBF, 0);
	lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
	fp = _fdopen(hConHandle, "r");
	*stdin = *fp;
	setvbuf(stdin, NULL, _IONBF, 0);
	lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
	hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
	fp = _fdopen(hConHandle, "w");
	*stderr = *fp;
	setvbuf(stderr, NULL, _IONBF, 0);
	ios::sync_with_stdio();
}


It creates a console window but cout doesn't print anything.
ttest2 function gets call every second and just in case i put cout there but still didn't print out anything.

I used to have a problem when I used cout before creating an costom console then it did the same like doing right now.

I double checked my code many times and now only using default libaries.
Cout is used only after console is create.

Any ideas?
Thanks you!

Edit:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

#define EXP __declspec(dllexport)  __stdcall
using namespace std;

void EXP ttest(int in)
{
	AllocConsole();
	cout << "Hello world!" << endl;
}

This code works but only second time.
First time the program is importing the dll and calling ttest it doesn't print anything.
Second time it does however this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

#define EXP __declspec(dllexport)  __stdcall
using namespace std;

void EXP ttest(int in)
{
	AllocConsole();
    AllocConsole();
	cout << "Hello world!" << endl;
}

Works exactly the same as code above. Doesn't print the first time...
Last edited on
I'll eventually get to looking at your issue Gyiove, as I do stuff like that too. But its taking me some time to get to it, as I have other stuff to take care of. Hopefully it isn't critical for you. I hope to look at in within a few days and will repost if someone else doesn't answer your question.
Thanks!

Gyiove,

I bought a new laptop with Windows 10 on it about 3 months ago for a particular project I’m working on and I immediately installed Visual Studio Community 2015 on it. The stuff you are stuck on with getting the C Runtime ( CRT ) stdin, stdout, and stderr console mode handles working, presumably within a GUI process, was one of the things I wanted eventually to test, as that’s something I fairly regularly use. I didn’t figure my existing code would work, because Microsoft fools around with these things every few years and wrecks them. There was one way of doing it back in old VC6 days circa 1998 or so. The next version of Visual Studio I bought was VS 2008 Pro. My VC6 code didn’t work anymore, and I had to figure out how to get it working with VC9 and I did (same as what you are using now). So when you posted your question here and said it wasn’t working in VC 2015 I figured that’s ‘par for the course’ (American slang for what’s expected, that is, that Microsoft would screw it up yet again).

I thought there was a fair chance I might be able to get that stuff working again like last time but I threw all of today at it and I couldn’t get it working. Finally I did an internet search on the cause of the problem, which is this from corecrt_wstdio.h …

1
2
3
4
5
6
7
8
9
10
typedef struct _iobuf
{
 void* _Placeholder;
} FILE;

_ACRTIMP_ALT FILE* __cdecl __acrt_iob_func(unsigned);

#define stdin  (__acrt_iob_func(0))
#define stdout (__acrt_iob_func(1))
#define stderr (__acrt_iob_func(2)) 


…and came upon this stackoverflow link…

http://stackoverflow.com/questions/30412951/unresolved-external-symbol-imp-fprintf-and-imp-iob-func-sdl2/30894349#30894349

The bottom line is I can’t get that stuff you are using working. Maybe somebody here more knowledgeable than I can.

For me, all I really need is to get printf working in an AllocateConsole() created console when called from a GUI process. I detest everything about the C++ Standard Library and have never used it, so iostream and std::cout are of no interest to me.

What has worked for me though with VC19 which is the C/C++ compiler which comes with Visual Studio Community 2015 is compiling/linking against my own version of the Standard C Library which I’ve written and I’ve named TCLib.lib (Tiny C Lib). In other words, I use a MSVC compiler switch known as /nodefaultlib, and that causes the linker to not use the C Runtime, which it otherwise loads by default. I’ve implemented all the C functions I need such as printf, wprintf, strlen, wcslen, fopen, fprintf, etc., etc., and they are in my TCLib. I’ve also implemented everything I need from the C++ Standard Library too, but that isn’t involved here. This is all likely of no use or interest to you, but if you would be interested in it I’d give it to you (or anyone who wants it). There’s no way of using std::cout though, or anything else from the C++ Standard Library, so be forewarned about that. Not unless you want to implement that yourself, that is, using the low level CRT functions in my TCLib.lib.

The reason I created my TCLib.lib and don’t link against the C Runtime or C++ Standard Libraries is because I want extremely small non-bloated executables and dlls. And by small I mean really, really small. Below is a GUI program that has a single button on its only window with the caption “Execute”. When you click the button it calls AllocateConsole() to create a console window and writes 10 strings to the console with printf(). It works just fine with the compiler/linker from Visual Studio Community 2015, which is VC19, and the resulting executable is 4608 bytes only, and requires no additional runtimes to execute…

continued...
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Main.cpp
// cl Main.cpp /O1 /Os /GS- /FeAllocConsole.exe /link TCLib.lib kernel32.lib user32.lib gdi32.lib
// Compiles/links to 4608 byte executable in x64
#include      <windows.h>   
#include      "stdio.h"
#include      "AllocateConsole.h"


LRESULT fnWndProc_OnCreate(WndEventArgs& Wea)
{
 HWND hButton;
	
 Wea.hIns=((LPCREATESTRUCT)Wea.lParam)->hInstance;  
 hButton=CreateWindow("button","Execute",WS_CHILD|WS_VISIBLE,70,35,141,30,Wea.hWnd,(HMENU)IDC_BUTTON,Wea.hIns,0);
 return 0;                                             
}


LRESULT fnWndProc_OnCommand(WndEventArgs& Wea)
{
 HMENU hSysMenu;
 unsigned int i;
  
 if(LOWORD(Wea.wParam)==IDC_BUTTON)
 {
    AllocConsole();
    hSysMenu=GetSystemMenu(GetConsoleWindow(),0);
    DeleteMenu(hSysMenu,6,MF_BYPOSITION);         
    for(i=0;i<10;i++)
        printf("%u\t%s\n",i,"Some Of The More Wicked Code I've Ever Written!");
 }

 return 0;
}


LRESULT fnWndProc_OnClose(WndEventArgs& Wea)   //This function handles the WM_CLOSE message
{                                           //sent when the 'x' button is clicked.
 if(MessageBox(Wea.hWnd,"Do You Wish To Exit This App?","Exit Check?",MB_YESNO)==IDYES)
 {
    DestroyWindow(Wea.hWnd);
    PostQuitMessage(WM_QUIT);
 }

 return 0;
}


LRESULT __stdcall fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 WndEventArgs Wea;

 for(size_t i=0; i<dim(EventHandler); i++)
 {
     if(EventHandler[i].iMsg==msg)
     {
        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
        return (EventHandler[i].fnPtr)(Wea);
     }
 }

 return (DefWindowProc(hwnd, msg, wParam, lParam));
}


int __stdcall WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{                                   
 char szClassName[]="AllocateConsole";  
 WNDCLASS wc;                     
 MSG messages;                     
 HWND hWnd;  
                      
 wc.lpszClassName=szClassName;                  wc.lpfnWndProc=fnWndProc;
 wc.style=0,                                    wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);     
 wc.hInstance=hIns,                             wc.hCursor=LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW,      wc.cbWndExtra=0;
 wc.lpszMenuName=NULL,                          wc.cbClsExtra=0; 
 RegisterClass(&wc);
 hWnd=CreateWindow(szClassName,"Allocate Console",WS_OVERLAPPEDWINDOW,900,700,300,150,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return (int)messages.wParam;
}


And the header…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//AllocateConsole.h
#define IDC_BUTTON                  1500
#define dim(x)                      (sizeof(x) / sizeof(x[0]))

struct                              WndEventArgs
{
 HWND                               hWnd;
 WPARAM                             wParam;
 LPARAM                             lParam;
 HINSTANCE                          hIns;
};

LRESULT fnWndProc_OnCreate          (WndEventArgs& Wea);
LRESULT fnWndProc_OnCommand         (WndEventArgs& Wea);
LRESULT fnWndProc_OnClose           (WndEventArgs& Wea);

struct EVENTHANDLER
{
 unsigned int                       iMsg;
 LRESULT                            (*fnPtr)(WndEventArgs&);
};

const EVENTHANDLER EventHandler[]=
{
 {WM_CREATE,                        fnWndProc_OnCreate},
 {WM_COMMAND,                       fnWndProc_OnCommand},
 {WM_CLOSE,                         fnWndProc_OnClose}
};


Going forward I don’t see myself linking against Microsoft’s versions of the C or C++ libraries simply because they are too bloated to suit me. I’ll be using my own libraries, which work using printf in console windows from GUI processes as the above program shows (you won’t be able to compile/link it without my TCLib.lib and my “stdio.h”). My way isn’t something very many C++ coders would be interested in though. In your case, unless someone else can figure it out, the only other possibility I can see is loading msvcrt.dll using LoadLibrary(), and using GetProcAddress() on the symbols from the old C Runtime which I believe would work. As an aside, that’s how I was able to get these techniques working in GUI apps written with PowerBASIC, which is another very high performance language I use occasionally (it makes much smaller binaries than Microsoft’s bloatware C/C++ compilers make, or even the newer GCC compilers).

Sorry I can’t get this working for you. I tried!
Thank you so much for putting so much effort into this!
One further thing I might mention, is that if you use the GCC compiler, for example one of the TDM releases, what you are doing should work (because it uses msvcrt.dll). Actually, you might have to back up to what I have for VC6 for that. What you have posted is like I have it for VC9 (Visual Studio 2008). I can post that if you need it (what will work with GCC and old VC6). So really, the whole issue and problem is VC19 and what Microsoft did in its refactoring of the CRT....

https://blogs.msdn.microsoft.com/vcblog/2014/06/10/the-great-c-runtime-crt-refactoring/
Last edited on
Topic archived. No new replies allowed.