How to create bare-minimum Windows Application with Console Access?

I'm following this [1] video tutorial and would like to run the code snippet at 1:07.

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
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <string>
#include <windows.h>
#include <cstdio>

LARGE_INTEGER frequency, a, b;
float elapsed_seconds;

using std::cout;
using std::cin;
using std::endl;
using std::to_string;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 
{
    QueryPerformanceFrequency(&frequency);
    cout << "Frequency: " << to_string(frequency.QuadPart) << " Ticks-Per-Second" << endl;

    QueryPerformanceCounter(&a);
    cout << "A: " << to_string(a.QuadPart);
    
    QueryPerformanceCounter(&b);
    cout << "B: " << to_string(b.QuadPart);

    elapsed_seconds = static_cast<float>(b.QuadPart - a.QuadPart) / frequency.QuadPart;
    cout << "Elapsed time (B-A): " << to_string(elapsed_seconds) << endl;

    system("Pause");
    return 0;
}


I'm using Visual Studio 2022 Community and have created an empty "Windows Desktop Wizard" application. I've right-clicked the main project > "Properties" > "Linker" > "System" > "Subsystem" and set this value to "Windows (/SUBSYSTEM:WINDOWS)".

The code compiles and builds but when I run the executable, I don't see any of the cout statements. Is there any VS settings I should set? Or have I misconfigured my project?

I just want to create a basic windows app, be able to use features from <windows.h> header, and interact with the app via console.

[1] Nick Walton: High Precision Timing on Windows in C
https://www.youtube.com/watch?v=LFkLLSOXQIc
By default a Windows gui program doesn't have a console. If you don't need a gui display it's easier to just have a console project. Change L15 to
int main() and set Subsystem to Console. If you do want a gui then after L16 insert AllocConsole() to get a console.
Ah - I see. I don't need to set Subsystem to "Windows (/SUBSYSTEM:WINDOWS)" nor do I need that overloaded main function to use the windows.h.

As you've said, I just needed the Subsystem set to Console, int main.

And this code will compile and run, with output to console.

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
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <string>
#include <windows.h>

LARGE_INTEGER frequency, a, b;
float elapsed_seconds;

using std::cout;
using std::cin;
using std::endl;
using std::to_string;

//int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
int main()
{
    QueryPerformanceFrequency(&frequency);
    cout << "Frequency: " << to_string(frequency.QuadPart) << " Ticks-Per-Second" << endl;

    QueryPerformanceCounter(&a);
    cout << "A: " << to_string(a.QuadPart);
    
    QueryPerformanceCounter(&b);
    cout << "B: " << to_string(b.QuadPart);

    elapsed_seconds = static_cast<float>(b.QuadPart - a.QuadPart) / frequency.QuadPart;
    cout << "Elapsed time (B-A): " << to_string(elapsed_seconds) << endl;

    system("Pause");
    return 0;
}


Thanks!
if the subject comes up, you can use the console in windows programs and windows in console programs if you really want to (you have to jump through some hoops to do so, but its possible). Usually mixing these is kind of dumb, but on occasion I have had a console program throw a messagebox pop up -- no reason not to, and it gets your attention :)

It is also handy sometimes to use the console in windows programs, but you usually want to do that *silently* such that the console is hidden. An example is to get the output of a console program that you called in the background.

for now keeping to console programs is probably ideal, but in the back of your mind, know that you can mix if you want to.
To illustrate what jonnin talks about, a console-mode app that pops up a message box message and outputs to the console.

1
2
3
4
5
6
7
8
9
#include <iostream>
#include <windows.h>

int main( )
{
   MessageBoxA( NULL, "Hello World!", "Hello Message", MB_OK );

   std::cout << "Hello World!\n";
}

FYI, using system("pause") is frowned upon for keeping a console window open. Read the "Console Closing Down" topic. All of it. https://cplusplus.com/forum/beginner/1988/

From what is suggested in that topic I crafted a header only library toolkit for pausing the console window from closing down.

https://github.com/GeorgePimpleton/cpp_misc_files/tree/main/Program%20Pauser%20Toolkit

I have two different versions of the toolkit available, pre-C++20 and C++20 using modules. You can use the header version even with C++20 and beyond.
One thing to note about using std::to_string:

cppreference wrote:
With floating point types std::to_string may yield unexpected results as the number of significant digits in the returned string can be zero

https://en.cppreference.com/w/cpp/string/basic_string/to_string

C++17's std::to_chars doesn't have this issue. https://en.cppreference.com/w/cpp/utility/to_chars

C++26 will redefine std::to_string in terms of C++20's std::format, so using std::format might be something worthwhile, its flexibility to being overloaded for custom types for example.
Using std::format, and explicitly the C++ min/max functions not the Windows min/max functions
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
#include <iostream>
#include <format>
#include <limits>

// use C++ min/max functions, not Windows
#define NOMINMAX
#include <windows.h>

int main( )
{
   LARGE_INTEGER frequency;
   LARGE_INTEGER a;
   LARGE_INTEGER b;

   QueryPerformanceFrequency( &frequency );
   std::cout << std::format("Frequency: {} Ticks-Per-Second\n", frequency.QuadPart );

   QueryPerformanceCounter( &a );
   std::cout << std::format("A: {}\n", a.QuadPart );

   QueryPerformanceCounter( &b );
   std::cout << std::format("B: {}\n", b.QuadPart );

   float elapsed_seconds = static_cast< float >( b.QuadPart - a.QuadPart ) / frequency.QuadPart;
   std::cout << std::format("Elapsed time (B-A): {}\n", elapsed_seconds );

   std::cout << "\nPress ENTER to continue...";
   std::cin.clear( );
   std::cin.sync( );
   std::cin.ignore( std::numeric_limits<std::streamsize>::max( ), '\n' );
}

Frequency: 10000000 Ticks-Per-Second
A: 2996187775081
B: 2996187778131
Elapsed time (B-A): 0.000305

Press ENTER to continue...
You can call AllocConsole() to get a console in a Windows (GUI) application – which is very useful to output some debug stuff.

But: Some extra work is needed to actually "connect" your stdout and stderr streams to the newly allocated console!

It is even possible to make std::cout and std::cerr 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
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
 	AllocConsole();

	std::unique_ptr<std::filebuf> stdout_buff;
	std::unique_ptr<std::filebuf> stderr_buff;

	if (FILE *const file = _wfreopen(L"CONOUT$", L"wb", stdout))
	{
		stdout_buff.reset(new std::filebuf(file));
		std::cout.rdbuf(stdout_buff.get());
	}

	if (FILE *const file = _wfreopen(L"CONOUT$", L"wb", stderr))
	{
		stdout_buff.reset(new std::filebuf(file));
		std::cerr.rdbuf(stdout_buff.get());
	}

	fprintf(stdout, "Test #1\n");
	fprintf(stderr, "Test #2\n");

	std::cout << "Test #3" << std::endl;
	std::cerr << "Test #4" << std::endl;

        /* ... */
}
Last edited on
Registered users can post here. Sign in or register to post.