I'm currently working on a C++ VS2015 project that makes an executable.
I have a file version.h that simply defines a bunch of numbers.
#define VERSION_MAJOR 3
#define VERSION_MINOR 0
#define VERSION_REVISION 0
#define VERSION_BUILD 2
#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
...
This version.h is used in the .rc file of the project to define the version information of the executable.
The .rc file looks like
#include "resource.h"
#include "version.h"
...
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILE_VERSION
...
So my problem is that every time I add a resource such that resource.h is modified, Visual Studio 2015 seems to remove the #include "version.h" in the .rc file and instead hard codes all the values found in "version.h".
Example .rc file of problem
#include "resource.h"
...
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,0,0,2
...
So my question is, how do I stop VS2015 from doing this?
You cannot actually stop Visual Studio's built-in resource editor from doing this. Any time that you use the resource editor (i.e., the GUI) to make changes to an item in a resource file, it will regenerate the resource file's code. This will clobber all sorts of manual tweaks made to a resource file, including substituting symbolic constants and/or arithmetic with literals, removing conditionally defined blocks of code, destroying careful manual formatting, and so on. As such, it is not a good idea to manually edit the resource file.
If you need to be able to make manual edits to a resource file that the resource editor will not clobber, then you can achieve that by adding a second resource file to your project. By convention, this has a .rc2
extension. Visual Studio's resource editor will never edit these resources directly, which means all editing must be done manually. But once you set it up correctly, all resources you put there will still be linked into your binary, making the end result equivalent.
This is pretty much the only way to get sane versioning, and I use it in my own projects. For example:
//
// MyProj.RC2 - resources Microsoft Visual C++ does not edit directly
//
#ifdef APSTUDIO_INVOKED
#error this file is not editable by Microsoft Visual C++
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "Version.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VERSION_MYPROJ_MAJOR,VERSION_MYPROJ_MINOR,VERSION_MYPROJ_REVISION,0
PRODUCTVERSION VERSION_MYPROJ_MAJOR,VERSION_MYPROJ_MINOR,VERSION_MYPROJ_REVISION,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Cody Gray"
VALUE "FileDescription", "The World's Greatest Application"
VALUE "FileVersion", VERSION_MYPROJ_FULL
VALUE "InternalName", "MyProj"
VALUE "LegalCopyright", "Copyrights are for suckers!"
VALUE "OriginalFilename", "MyProj.exe"
VALUE "ProductName", "MyProj"
VALUE "ProductVersion", VERSION_MYPROJ_FULL
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
You can put other resources here, too. For example, in one application that I'm working on now, I have a dialog box resource that I only want to get linked into "debug" builds (it is for configuring internal, debug-related options). I tried wrapping the dialog box's definition with #ifdef DEBUG
, but the resource editor stripped that entire block out each time it ran, so that was a no-go. Instead, I moved the dialog box's definition into my .rc2
file, keeping it wrapped in the #ifdef
. I lost the ability to edit it with the resource editor, but I don't care so much about that since I can edit it just as quickly by hand in the rare event that I need to make changes. And at least it doesn't get automatically stripped out.
The final key is getting this .rc2
file to be compiled by the resource editor and linked into your binary. To do that, you will need to edit your main resource file (.rc
), but this change will get preserved. The part you want to edit are the TEXTINCLUDE
resources. In my .rc
file, that section looks something like this:
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"Resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#ifndef APSTUDIO_INVOKED\r\n"
"#include ""TargetVer.h""\r\n"
"#endif\r\n"
"#include ""AfxRes.h""\r\n"
"#include ""VerRsrc.h""\r\n"
"#include ""Version.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
"LANGUAGE 9, 1\r\n"
"#include ""MyProj.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
"#include ""AfxRes.rc"" // standard components\r\n"
"#endif\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
The important part is where MyProj.rc2
is #included in the 3rd TEXTINCLUDE
section. Any text here is dumped directly into the resource file whenever the resource compiler runs, so at the end of your resource file, you'll see a familiar-looking auto-generated section like:
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
#include "MyProj.rc2" // non-Microsoft Visual C++ edited resources
#include "AfxRes.rc" // standard components
#endif
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
It bears mentioning, in case you can't figure out how to put the pieces together from my examples here, that the MFC project template in Visual Studio sets this all up for you automatically, as described in this technical note.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With