emendelson
emendelson

Reputation: 545

C++ (VC2010) Help converting console app to hidden Windows app?

I've read more than a dozen pages explaining how to convert a Win32 console application into a Windows application that will run without briefly opening and closing a console window, but I'm too much of a beginner to get it to work.

For example, in VC2010 I made the two changes in the project properties described here:

convert a console app to a windows app

and changed Main to WinMain but of course got error messages from the compiler.

Following other pages, I also tried creating a console application, then, in the Win32 Application Wizard, and changing the Application Type to a Windows application, but I can't figure out what to do next. I've tried changing int Main to int CALLBACK WinMain, but of course that doesn't work either.

Is there anyone who can help a beginner with this? Here is what I think is the relevant part of my code EDIT: the complete code, for anyone who wonders what this is for, is here:

https://www.dropbox.com/s/1h8x1k2zv0lc5d1/vPasteCPlus.txt?dl=0

#include <stdafx.h>
#include <windows.h>
#include <iostream>
#include <fstream>
#include <codecvt> // for wstring_convert
#include <locale>  // for codecvt_byname
using namespace std;

// helper to get path to this application
string ExePath() {
char buffer[MAX_PATH];
GetModuleFileNameA( NULL, buffer, MAX_PATH );
string::size_type pos = string( buffer ).find_last_of( "\\/" );
return string( buffer ).substr( 0, pos);
}

int main(int argc, char* argv[])
{
    // get the command-line argument if any, and do various things
} 

Again, apologies for this beginner question. The only experience I have with C++ is writing console applications, and any advice will be gratefully received.

Upvotes: 0

Views: 1204

Answers (2)

grisha
grisha

Reputation: 1297

Ok, so you have opened Visual Studio. And you have Solution Explorer (If not, View -> Solution Explorer).

First of all, to make Windows application, you should change entry point from main() (C++ standard) to Windows-specific WinMain(). See msdn for more detailed description. So, you are changing main() to next one (copy-paste from documentation):

int CALLBACK WinMain(
  _In_ HINSTANCE hInstance,
  _In_ HINSTANCE hPrevInstance,
  _In_ LPSTR     lpCmdLine,
  _In_ int       nCmdShow)
{
    return 0;
}

Of course, you should include <Windows.h>, because Windows provides it own API for working with system (such as LPSTR type). In a nutshell, you did all that compiler need to compile your program. And you can build your solution (Build -> Build Solution)... This will lead to linker error:

error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup

Again, compiler did everything you want and compiles your source file into .obj, but, because, your project is configured for Console application, linker needs standard entry point for Console application - main and it can't found (resolve) it in our case, because we changed main to WinMain. To make linker happy, you should tell it:

  • Right click on project inside Solution Explorer
  • Then click on Properties: Solution Explorer Properties
  • Go to Configuration Properties -> Linker -> System and set SubSystem to Windows: Linker's SubSystem configuration

Try to build your application again and voila - you have no linker error already because your linker knows now that it need to produce Windows application and found Windows entry point: WinMain() !

About this one:

// get the command-line argument if any, and do various things

you should use lpCmdLine parameter of WinMain(). But be carefully, if you run your program (so.exe, for example) like this one:

so.exe arg1 arg2

lpCmdLine is arg1 arg2 string. There is a lot of stuff of what you can do to get arg1 and arg2 asn an array like in main() argv (with argc), but you can explore:

and relative stuff (such as wchar_t on Windows)

Upvotes: 1

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145239

If this is a Visual Studio project (as the <stdafx.h> strongly indicates) then:

  • Set the subsystem to Windows in the linker settings.
  • Set the entry point to mainCRTStartup (which calls standard main).

But are you sure that you want this?

It sounds more that what you want is a Windows service?

Upvotes: 0

Related Questions