如何阻止Visual Studio 2015进行硬编码版本控制

H. *_*ock 6 visual-studio visual-c++ visual-studio-2015

我目前正在开发一个可执行的C++ VS2015项目.

我有一个文件version.h,它只是定义了一堆数字.

#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
...
Run Code Online (Sandbox Code Playgroud)

version.h用于项目的.rc文件中,以定义可执行文件的版本信息.

.rc文件看起来像

#include "resource.h"
#include "version.h"
...
VS_VERSION_INFO VERSIONINFO
 FILEVERSION VER_FILE_VERSION
 ...
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,每次添加资源以修改resource.h时,Visual Studio 2015似乎都会删除.rc文件中的#include"version.h",而是硬编码"version"中的所有值. H".

示例.rc文件的问题

#include "resource.h"
...
VS_VERSION_INFO VERSIONINFO
 FILEVERSION 3,0,0,2
 ...
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,如何阻止VS2015这样做呢?

Cod*_*ray 5

您实际上不能停止Visual Studio的内置资源编辑器执行此操作。每当您使用资源编辑器( GUI)对资源文件中的项目进行更改时,都会重新生成资源文件的代码。这将破坏对资源文件进行的各种手动调整,包括用文字替换符号常量和/或算术,删除有条件定义的代码块,破坏仔细的手动格式化等等。因此,手动编辑资源文件不是一个好主意。

如果您需要能够对资源文件进行手动编辑,而资源编辑器不会破坏它,则可以通过向项目中添加第二个资源文件来实现。按照惯例,这是一个.rc2扩展。Visual Studio的资源编辑器永远不会直接编辑这些资源,这意味着所有编辑都必须手动完成。但是,一旦正确设置,放置在其中的所有资源仍将链接到二进制文件中,从而使最终结果相同。

这几乎是获得合理版本控制的唯一方法,我在自己的项目中使用它。例如:

//
// 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
Run Code Online (Sandbox Code Playgroud)

您也可以在此处放置其他资源。例如,在我现在正在处理的一个应用程序中,我有一个对话框资源,我只想链接到“调试”构建中(用于配置内部的与调试相关的选项)。我尝试#ifdef DEBUG用来包装对话框的定义,但是每次运行时资源编辑器都会删除整个块,所以这是不可行的。取而代之的是,我将对话框的定义移到了我的.rc2文件中,并将其包裹在中#ifdef。我失去了使用资源编辑器进行编辑的能力,但是我对此并不在意,因为在需要更改的罕见事件中,我可以手动编辑它的速度如此快。而且至少它不会自动剥离。

最后的关键是让该.rc2文件由资源编辑器编译并链接到您的二进制文件中。为此,您将需要编辑主资源文件(.rc),但此更改将保留下来。您要编辑的部分是TEXTINCLUDE资源。在我的.rc文件中,该部分如下所示:

/////////////////////////////////////////////////////////////////////////////
//
// 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
Run Code Online (Sandbox Code Playgroud)

重要的部分是MyProj.rc2第3 TEXTINCLUDE部分中的#include 。每当运行资源编译器时,此处的任何文本都会直接转储到资源文件中,因此,在资源文件的末尾,您将看到一个看起来很熟悉的自动生成的部分,例如:

#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
Run Code Online (Sandbox Code Playgroud)

值得一提的是,如果您无法在此处的示例中弄清楚如何将各个部分放在一起,则如本技术说明中所述,Visual Studio中的MFC项目模板会自动为您进行设置。