Category: Visual Studio

  • Setting a Debug Breakpoint in a Win32 API in Visual Studio

    Recently, I was stress-testing an application of mine and noticed that the handle count kept growing. After a quick check in Process Explorer I saw that the handle was for a registry key. I was curious as to where the key was being opened in the first place but, it wasn’t in my code so I couldn’t just set a breakpoint on a line in my source. Wouldn’t it be nice if you could set a breakpoint on a function in Visual Studio but that’s not in your code?

    You can! If you have the NT symbols loaded for your system, then you can set a breakpoint on any public function. In my particular case, I set a breakpoint on RegOpenKey and RegOpenKeyEx for both ANSI and UNICODE versions of the function.

    {,,Advapi32.dll}_RegOpenKeyA@12
    {,,Advapi32.dll}_RegOpenKeyW@12
    {,,Advapi32.dll}_RegOpenKeyExA@20
    {,,Advapi32.dll}_RegOpenKeyExW@20

    Note that you have to use the decorated name of the function. For Win32 API functions, you have to put an underscore before the function name and remember that many functions are macro redirected to ANSI or UNICODE versions with an A or W extension. Since most functions use the __stdcall calling convention the @<number> is generally 4x the number of arguments. So for RegOpenKey for example, it’s redirected to RegOpenKeyA or RegOpenKeyW and has 3 arguments, so it’s decorated name is _RegOpenKeyA@12 and _RegOpenKeyW@12.

    Similarly, you can set breakpoints in third-party libraries for public functions which assumes that you have a PDB for it.

    UPDATE 2011-11-13: You only have to use the decorated name of the function for 32-bit applications. For 64-bit applications, the names are undecorated, like this:

    {,,Advapi32.dll}RegOpenKeyA
    {,,Advapi32.dll}RegOpenKeyW
    {,,Advapi32.dll}RegOpenKeyExA
    {,,Advapi32.dll}RegOpenKeyExW

    Related: Can I Add a Breakpoint on CreateProcess in VS

  • Targeting Windows 2000/XP RTM/XP SP1 from Visual Studio 2010

    I’m currently working on a little native C application using the C-runtime libraries (CRT) to detect Windows power events. I ran into a problem when testing my application on Windows XP Professional 32-bit RTM (e.g. “Gold Release”, no service packs). When I attempt to run the application, I get the following error message:

    Entry Point Not Found
    Entry Point Not Found. The procedure entry point DecodePointer could not be located in the dynamic link library KERNEL32.dll.

    Huh?!

    After a little digging, it turns out the Microsoft rather quietly discontinued targeting the Windows 2000 and Windows XP RTM/SP1 platforms with Visual Studio 2010. The last release that will target these platforms is Visual Studio 2008.

    There were various suggestions on how to workaround this issue including recompiling the CRT, implementing the missing functions in your own w2kcompat.lib, FASM/MASM assembly magic, and reverting to using Visual Studio 2008.  However all of these offered significant drawbacks for me. I do not want to be in the business of supporting a custom compiled version of the CRT. I don’t understand the assembly editing based solutions sufficiently to feel comfortable supporting them on x86 and x64 platforms in the field.

    The workaround that works for me and that I ultimately used is to target the Visual Studio 2008 (VC 9.0) Platform Toolset from within my Visual Studio 2010 projects as suggested here and here. There were three key upsides for me with this solution:

    1. This seems like the most reasonable option to support in deployments. No custom builds and no assembly hacking.
    2. I can continue to use VS2k10 and all it’s goodness. (Well, almost. Any feature added in the VC10 runtime won’t be available. )
    3. This modification can be done on a per project (and actually, per Build Configuration) basis, so I don’t have to make system-wide changes to my VS install.

    The major downside to this option is that it requires me to have Visual Studio 2008 installed, but this was something I was willing to live with.

    One way to accomplish this workaround that was suggested is to place the path to the Visual Studio 2008 VC libs (e.g. “C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\lib” for 32-bit builds) first in the Additional Library Directories under the Linker options for your project. This messy because you have to do this for every configuration of every project in your solution that needs it and it varies for x86 versus x64 builds. Making matters worse is that the location of these files may vary from system to system, so what works for one developer’s machine may not work for another. Not ideal.

    The cleaner and easier way to do this is to set the Platform Toolset in the project’s general properties pane. You still need to do this for each project as well as all configurations and all platforms. However, unlike the previous method, this one uses the same value across configurations and platforms and it’s portable across machines.

    Setting the Platform Toolset in Visual Studio 2010
    Setting the Platform Toolset in Visual Studio 2010
  • Integrating the Subversion Revision into the Version Automatically with .NET

    In our final post in this series, we’ll be discussing how to integrate the Subversion information into the file version automatically with .NET. Building on these previous posts, I’ll be discussing how to do this for a .NET project using Visual Studio 2010 Professional and TortoiseSVN.

    The source code for this post is available here.

    Step 1: Add a Version Project

    I find adding a specific Version project to the solution is beneficial. The reason is that we are generating common version info to be used across the entire solution, however the first project in the build order needs to be the one to generate this info. Depending on your project dependencies there may not be an obvious or good place to do this. By adding a Version project and making all other projects depend on it we have an easy place to generate the necessary files.

    1. Add a project named Version to your Solution
    2. Add a reference to Version from all the other projects in your Solution

    Step 2: Add a GlobalAssemblyInfo Template

    Create a file named GlobalAssemblyInfo.cs.tmpl in the Properties folder of the Version project. Copy the code below into the template and make any desired customizations to match your environment.

    Notice the $WCNOW$, $WCNOW$ and $WCMODS?M:$ tokens. We’ll use these to place the necessary Subversion information in the file we generate using SubWCRev.exe.

    // This file contains common AssemblyVersion data to be shared across all projects in this solution.
    using System.Reflection;
    
    [assembly: AssemblyCompany("Zach Burlingame")]
    [assembly: AssemblyProduct("DotNetSVNAutoVersion")]
    [assembly: AssemblyCopyright("Copyright © Zach Burlingame 2011")]
    [assembly: AssemblyTrademark("")]
    [assembly: AssemblyCulture("")]
    
    #if DEBUG
    [assembly: AssemblyConfiguration("Debug")]
    #else
    [assembly: AssemblyConfiguration("Release")]
    #endif
    
    // Version information for an assembly consists of the following four values:
    //
    //      Major Version
    //      Minor Version 
    //      Revision
    //      Build
    [assembly: AssemblyVersion("1.0.0.$WCREV$")]
    [assembly: AssemblyTitle("Built $WCNOW$ from r$WCREV$$WCMODS?M:$")] // This is visible as the "File Description" on the Details tab of the Explorer pane
    

    NOTE: Originally I also had set the AssemblyFileVersion in the template as well. However, for .NET projects, placing string data in this attribute will generate a warning (like the one below), unlike the FileVersionStr in native projects.

    [assembly: AssemblyFileVersion(“1.0.0.$WCREV$$WCMODS?M:$”)]
    Warning 1 Assembly generation — The version ‘1.0.0.118M’ specified for the ‘file version’ is not in the normal ‘major.minor.build.revision’ format Version

    Step 3: Using SubWCRev to Generate GlobalAssemblyInfo

    Next we need to add a pre-build step to our Version project to generate the GlobalAssemblyInfo.cs file from the template using the TortoiseSVN tool called SubWCRev.

    The extracted version info includes the revision number, the date time of the build and if there are any local modifications to the working copy. Note that in counter-intuitive fashion, the AssemblyTitle attribute is what sets the Description field when viewed from the Details tab of the Properties pane in Explorer. Meanwhile the AssemblyDescription field isn’t displayed at all and rather is only accessible through API calls against the binary. Why MS did this, I do not know…

    1. Right-click on the Version project
    2. Select Properties
    3. Select the Build Events tab
    4. In the Pre-build event command line box, enter:
      subwcrev.exe "$(SolutionDir)\" "$(ProjectDir)Properties\GlobalAssemblyInfo.cs.tmpl" "$(SolutionDir)Code\App\GlobalAssemblyInfo.cs"

    Step 4: Add a link to the GlobalAssemblyInfo.cs file in each project

    1. In Visual Studio, right-click on a project
    2. Select Add->Existing Item
    3. Browse to GlobalAssemblyInfo.cs
    4. Select the file
    5. Click the drop-down arrow next to Add and select Add As Link
    6. Move the link to your Properties folder (optional, but keeps things neat)

    Step 5: Update the AssemblyInfo.cs for each project

    In order to avoid duplicate annotations for assembly information, you must remove entries from the AssemblyInfo.cs file that appear in the GlobalAssemblyInfo.cs file. In our example here, this is what we end up with:

    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    
    // General Information about an assembly is controlled through the following 
    // set of attributes. Change these attribute values to modify the information
    // associated with an assembly.
    [assembly: AssemblyDescription("")]  // This is not visible on the Details tab of the Explorer pane
    
    // Setting ComVisible to false makes the types in this assembly not visible 
    // to COM components.  If you need to access a type in this assembly from 
    // COM, set the ComVisible attribute to true on that type.
    [assembly: ComVisible(false)]
    
    // The following GUID is for the ID of the typelib if this project is exposed to COM
    [assembly: Guid("dad09178-814d-43f4-b76d-0fbe29a32544")]
    

    Other Posts in this Series

    1. Mapping Binaries in the Field to Source Code in the Repository
    2. Versioning a Native C/C++ Binary with Visual Studio
    3. Versioning a .NET Assembly with Visual Studio
    4. Integrating the Mercurial Revision into the Version Automatically with Native C/C++
    5. Integrating the Mercurial Revision into the Version Automatically with .NET
    6. Integrating the Subversion Revision into the Version Automatically with Native C/C++
    7. Integrating the Subversion Revision into the Version Automatically with .NET
  • Integrating the Subversion Revision into the Version Automatically with Native C/C++

    We’ve covered how to automatically include the mercurial revision into the version. Now how about doing this for Subversion?

    The basics of how to accomplish this are much the same as in the mercurial example. The major difference is that I don’t use WSH to generate the version file. Unlike TortoiseHg, which includes the CLI tools for Mercurial, TortoiseSVN does not. Therefore you have two choices:

    1. Download a CLI SVN implementation like SlikSVN and implement a script similar to the one that we did for Hg.
    2. Use the SubWCRev.exe utility that comes with TortoiseSVN to generate your version file from a template

    Since I already use TortoiseSVN and SubWCRev has already done the heavy-lifting for me, I’ve decided to go that route. As usual, I’ll be doing my example using Visual Studio 2010 Professional although these techniques should work on other versions of VS as well.

    The source code for this post is available here.

    Step 1: Setup Basic Versioning

    First we need to have the basic building blocks in place, as discussed in Versioning a Native C/C++ Binary with Visual Studio

    Step 2: Add an SVN Version Template

    Next we create a file named svn_version.h.tmpl in our project. I generally keep it under the Resources filter. This file serves as the basis of the SVN version header that we ultimately want to include in our project. The tokens (e.g. $WCREV$) will be automatically replaced by the SubWCRev utility later.

    #ifndef _SVN_VERSION_H_
    #define _SVN_VERSION_H_
    
    #define SVN_LOCAL_MODIFICATIONS $WCMODS?1:0$  // 1 if there are modifications to the local working copy, 0 otherwise
    #define SVN_REVISION            $WCREV$       // Highest committed revision number in the working copy
    #define SVN_TIME_NOW            $WCNOW$       // Current system date &amp; time
    
    #endif
    

    Step 3: Add the Pre-build Step

    Finally we need to add a pre-build step which will execute the SubWCRev tool, thus generating the svn_version.h file prior to the binary being built.

    1. Right-click on your project
    2. Select Properties
    3. Click Build Events
    4. Click Pre-Build Event
    5. In the Configuration drop-down, select All Configurations
    6. In the Command Line field, enter:
      SubWCRev.exe $(SolutionDir) $(ProjectDir)\svn_version.h.tmpl $(ProjectDir)\svn_version.h
    7. In the Description field, add a comment such as:
      Generate the svn_version.h file with the necessary repo identify info for versioning

    NOTE:If you have multiple projects in the same solution that all need to use the same information from Subversion you have a few choices. One is to put the template and pre-build event in one project which all the other projects depend on and add a link to the svn_version.h file that gets generated. Another option is to create a specific version project that all it does is generate the svn_version.h file and define common version information and then have every project in the solution depends on it so it’s executed first in the build order.

    Step 4: Update Version.h

    The version.h file we created in the basic versioning post needs to be updated to include the generated svn_version.h file and to make use of its defines.

    #include "svn_version.h"
    
    #define STRINGIZE2(s) #s
    #define STRINGIZE(s) STRINGIZE2(s)
    
    #define VERSION_MAJOR               1
    #define VERSION_MINOR               0
    #define VERSION_REVISION            0
    #define VERSION_BUILD               SVN_REVISION
    
    #if SVN_LOCAL_MODIFICATIONS
      #define VERSION_MODIFIER "M"
    #else
      #define VERSION_MODIFIER
    #endif
    
    #define VER_FILE_DESCRIPTION_STR    "Built " STRINGIZE(SVN_TIME_NOW) " from r" STRINGIZE(SVN_REVISION)
    #define VER_FILE_VERSION            VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
    #define VER_FILE_VERSION_STR        STRINGIZE(VERSION_MAJOR)        \
                                        "." STRINGIZE(VERSION_MINOR)    \
                                        "." STRINGIZE(VERSION_REVISION) \
                                        "." STRINGIZE(VERSION_BUILD)    \
                                        VERSION_MODIFIER
    
    #define VER_PRODUCTNAME_STR         "c_svn_autoversion"
    #define VER_PRODUCT_VERSION         VER_FILE_VERSION
    #define VER_PRODUCT_VERSION_STR     VER_FILE_VERSION_STR
    
    #if LIBRARY_EXPORTS
      #define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".dll"
    #else
      #define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".exe"
    #endif
    #define VER_INTERNAL_NAME_STR       VER_ORIGINAL_FILENAME_STR
    
    #define VER_COPYRIGHT_STR           "Copyright (C) 2011"
    
    #ifdef _DEBUG
      #define VER_VER_DEBUG             VS_FF_DEBUG
    #else
      #define VER_VER_DEBUG             0
    #endif
    
    #define VER_FILEOS                  VOS_NT_WINDOWS32
    #define VER_FILEFLAGS               VER_VER_DEBUG
    
    #if LIBRARY_EXPORTS
      #define VER_FILETYPE              VFT_DLL
    #else
      #define VER_FILETYPE              VFT_APP
    #endif
    

    Step 6: Add SVN Ignore on svn_version.h

    Finally, we need to go ahead and add an svn:ignore on svn_version.h because we don’t want its difference checking in every commit and we don’t want it constantly marking the working copy as modified if it’s tracked.

    Results

    Now when each time you build your projects, the latest Subversion information of the working copy is automatically included in the file version information.

    Version info with Subversion
    Version info with Subversion

    Final Thoughts

    So there you have it, you can now automatically include all the necessary information from your Subversion working copy in your build to map them one-to-one with the source code that was used.

    Other Posts in this Series

    1. Mapping Binaries in the Field to Source Code in the Repository
    2. Versioning a Native C/C++ Binary with Visual Studio
    3. Versioning a .NET Assembly with Visual Studio
    4. Integrating the Mercurial Revision into the Version Automatically with Native C/C++
    5. Integrating the Mercurial Revision into the Version Automatically with .NET
    6. Integrating the Subversion Revision into the Version Automatically with Native C/C++
    7. Integrating the Subversion Revision into the Version Automatically with .NET
  • Integrating the Mercurial Revision into the Version Automatically with .NET

    I’ve already shown how you can add the mercurial revision into the version automatically with native C/C++. However, there are some extra hurdles you have to jump to make this work for .NET. The problem is that you can’t use static variables or class data in the assembly attributes – you have to use constant literals or expressions. As a result, we can’t just generate a simple class and reference it in the AssemblyAttributes.

    Again I’ll be building on the previous posts and discussing how to do this with Visual Studio 2010 Professional and Mercurial using TortoiseHg, this time for a .NET application. Other versions of Visual Studio should work similarly and other Mercurial packages will work as well, as long as they provide command-line tools that are in the path of your IDE. We’ll be using a GlobalAssemblyInfo file to share common assembly attributes across projects in the same solution as discussed here.

    The source code for this post is available here.

    Step 1: Add a Version Project

    Although I didn’t do this for the native solution, I find adding a specific Version project to the solution is beneficial. The reason is that we are generating common version info to be used across the entire solution, however the first project in the build order needs to be the one to generate this info. Depending on your project dependencies there may not be an obvious or good place to do this. By adding a Version project and making all other projects depend on it we have an easy place to generate the necessary files.

    1. Add a project named Version to your Solution
    2. Add a reference to Version from all the other projects in your Solution

    Step 2: Add a GlobalAssemblyInfo Template

    Rather than generate the entire contents of the GlobalAssemblyInfo.cs file in the script, where it’s harder to find and edit when needed, we’ll use a template. Create a file named GlobalAssemblyInfo.cs.tmpl in the Properties folder of the Version project. Copy the code below into the template and make any desired customizations to match your environment.

    Notice the $REVISION$, $CHANGESET$ and $LOCAL_MODIFICATIONS$ tokens. We’ll use these to place the necessary Mercurial information in the file we generate.

    // This file contains common AssemblyVersion data to be shared across all projects in this solution.
    using System.Reflection;
    
    [assembly: AssemblyCompany("Zach Burlingame")]
    [assembly: AssemblyProduct("DotNetHgAutoVersion")]
    [assembly: AssemblyCopyright("Copyright © Zach Burlingame 2011")]
    [assembly: AssemblyTrademark("")]
    [assembly: AssemblyCulture("")]
    
    #if DEBUG
    [assembly: AssemblyConfiguration("Debug")]
    #else
    [assembly: AssemblyConfiguration("Release")]
    #endif
    
    // Version information for an assembly consists of the following four values:
    //
    //      Major Version
    //      Minor Version
    //      Revision
    //      Build
    [assembly: AssemblyVersion("1.0.0.$REVISION$")]
    [assembly: AssemblyTitle("$CHANGESET$$LOCAL_MODIFICATIONS$")]   // This is visible as the "File Description" on the Details tab of the Explorer pane
    

    Step 3: Using WSH to Generate Global Assembly

    Next we need to add a file to our Version project named hg_version.jse. Personally, I like to add this file under the Properties filter of my project. Copy the code below in to the script file. This code does two things:

    1. Creates GlobalAssemblyInfo.cs
    2. Extracts the desired Mercurial version info from the working copy and places it in the header

    The extracted version info includes the full node identity, the revision number and if there are any local modifications to the working copy. Note that in counter-intuitive fashion, the AssemblyTitle attribute is what sets the Description field when viewed from the Details tab of the Properties pane in Explorer. Meanwhile the AssemblyDescription field isn’t displayed at all and rather is only accessible through API calls against the binary. Why MS did this, I do not know…

    var fso   = new ActiveXObject("Scripting.FileSystemObject");
    var shell = new ActiveXObject("WScript.Shell");
    var ForReading = 1, ForWriting = 2, ForAppending = 8;
    
    var projectDir = "../../";
    
    var hgRevNum               = shell.Exec("hg identify --num");
    var rev                    = hgRevNum.StdOut.ReadAll();
    var hg_revision            = String(rev).replace(/\n/g,"").replace(/\+/g,"");
    var hg_local_modifications = '';
    
    if( String(rev).replace(/\n/g, "").indexOf("+") != -1 )
    {
       hg_local_modifications = '+';
    }
    
    var hgChangeset  = shell.Exec("hg parents --template \"{node}\"");
    var changeset    = hgChangeset.StdOut.ReadAll();
    var hg_changeset = String(changeset).replace(/\n/g,"");
    
    var hgChangesetShort    = shell.Exec("hg parents --template \"{node|short}\"");
    var changeset_short     = hgChangesetShort.StdOut.ReadAll();
    var hg_changeset_short  = String(changeset_short).replace(/\n/g,"");
    
    var tmplFile = fso.OpenTextFile( projectDir + 'Properties/GlobalAssemblyInfo.cs.tmpl', ForReading, false );
    var strContents = tmplFile.ReadAll();
    tmplFile.Close();
    
    strContents = String(strContents).replace(/\$REVISION\$/g, hg_revision );
    strContents = String(strContents).replace(/\$LOCAL_MODIFICATIONS\$/g, hg_local_modifications );
    strContents = String(strContents).replace(/\$CHANGESET\$/g, hg_changeset );
    strContents = String(strContents).replace(/\$SHORT_CHANGESET\$/g, hg_changeset_short )
    
    var asmFile = fso.CreateTextFile( projectDir + '../GlobalAssemblyInfo.cs', ForWriting, true );
    asmFile.Write( strContents );
    asmFile.Close();
    

    Step 4: Add a Pre-build Event

    Add a pre-build event to the Version project to call the hg_version.jse script and generate GlobalAssemblyInfo.cs.

    1. Right-click on the Version project
    2. Select Properties
    3. Select the Build Events tab
    4. In the Pre-build event command line box, enter:
      cscript.exe “$(ProjectDir)\Properties\hg_version.jse”

    Step 5: Add a link to the GlobalAssemblyInfo.cs file in each project

    1. In Visual Studio, right-click on a project
    2. Select Add->Existing Item
    3. Browse to GlobalAssemblyInfo.cs
    4. Select the file
    5. Click the drop-down arrow next to Add and select Add As Link
    6. Move the link to your Properties folder (optional, but keeps things neat)

    Step 6: Update the AssemblyInfo.cs for each project

    In order to avoid duplicate annotations for assembly information, you must remove entries from the AssemblyInfo.cs file that appear in the GlobalAssemblyInfo.cs file. In our example here, this is what we end up with:

    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    
    // General Information about an assembly is controlled through the following
    // set of attributes. Change these attribute values to modify the information
    // associated with an assembly.
    [assembly: AssemblyDescription("")]  // This is not visible on the Details tab of the Explorer pane
    
    // Setting ComVisible to false makes the types in this assembly not visible
    // to COM components.  If you need to access a type in this assembly from
    // COM, set the ComVisible attribute to true on that type.
    [assembly: ComVisible(false)]
    
    // The following GUID is for the ID of the typelib if this project is exposed to COM
    [assembly: Guid("dad09178-814d-43f4-b76d-0fbe29a32544")]
    

    Conclusion

    And there you have it! Now when you build your solution, all your project assemblies will have the latest Mercurial version information included in their meta-data automatically.

    Other Posts in this Series

    1. Mapping Binaries in the Field to Source Code in the Repository
    2. Versioning a Native C/C++ Binary with Visual Studio
    3. Versioning a .NET Assembly with Visual Studio
    4. Integrating the Mercurial Revision into the Version Automatically with Native C/C++
    5. Integrating the Mercurial Revision into the Version Automatically with .NET
    6. Integrating the Subversion Revision into the Version Automatically with Native C/C++
    7. Integrating the Subversion Revision into the Version Automatically with .NET
  • Integrating the Mercurial Revision into the Version Automatically with Native C/C++

    Now that we’ve covered why we should include version information in our binaries and how to do that for native C/C++ and managed .NET projects, it’s time to up our game. One of the major shortfalls of the previous solutions is that the version information on the binary didn’t map one-to-one to revisions from source control. As a result, while you may be able to determine the version of a particular file, you can’t easily get to the corresponding source code, if at all. One solution to this is to include the source control revision information in the version so you know exactly what was used to build it. Here I’ll be building on the previous posts and discussing how to do this with Visual Studio 2010 Professional and Mercurial using TortoiseHg for a native C/C++ application. Other versions of Visual Studio should work similarly and other Mercurial packages will work as well, as long as they provide command-line tools that are in the path of your IDE. The steps can be easily modified for use with a .NET project based on the previous post.

    Update 2011/02/17: Doing this for a .NET assembly is actually a bit trickier than I originally thought because you can’t use static variables or class data in the assembly attributes – you have to use constant literals or expressions. I’ll do a separate post on how to do this with a .NET project.

    The basic concept of how this works is explained in the here. The source code for this post is available here.

    Step 1: Using WSH to Generate a Version Header

    The first step is to add a file to your project named hg_version.jse. Personally, I add this file under the Resource filter of my project. Copy the code below in to the script file. This code does two things:

    1. Creates hg_version.h
    2. Extracts the desired Mercurial version info from the working copy and places it in the header

    The extracted version info includes the full node identity, the short node identity, the revision number, and if there are any local modifications to the working copy.

    var fso   = new ActiveXObject("Scripting.FileSystemObject");
    var shell = new ActiveXObject("WScript.Shell");
    
    var outFile = fso.CreateTextFile("hg_version.h", true);
    
    var hgRevNum               = shell.Exec("hg identify --num");
    var rev                    = hgRevNum.StdOut.ReadAll();
    var hg_revision            = String(rev).replace(/\n/g,"").replace(/\+/g,"");
    var hg_local_modifications = 0
    if( String(rev).replace(/\n/g, "").indexOf("+") != -1 )
    {
       hg_local_modifications = 1;
    }
    outFile.WriteLine( "#define HG_REVISION               " + hg_revision );
    outFile.WriteLine( "#define HG_LOCAL_MODIFICATIONS    " + hg_local_modifications );
    
    var hgChangeset  = shell.Exec("hg parents --template \"{node}\"");
    var changeset    = hgChangeset.StdOut.ReadAll();
    var hg_changeset = String(changeset).replace(/\n/g,"");
    outFile.WriteLine( "#define HG_CHANGESET              \"" + hg_changeset +"\"" );
    
    var hgChangesetShort    = shell.Exec("hg parents --template \"{node|short}\"");
    var changeset_short     = hgChangesetShort.StdOut.ReadAll();
    var hg_changeset_short  = "#define HG_CHANGESET_SHORT        \"" + String(changeset_short).replace(/\n/g,"") + "\"";
    outFile.WriteLine( hg_changeset_short );
    
    outFile.Close();
    

    Step 2: Update Version.h

    The version.h file we created in a previous post needs to be updated to use the information from the generated header. The mercurial revision number is a human friendly integer and can be used directly in the file version. However, due to the nature of a DVCS it is not guaranteed to be globally unique (and it often won’t be on projects with multiple developers using common workflow patterns). The node identity however, does uniquely identify the changeset globally. We include this information in the file description field which maps the binaries one-to-one with the source code they were built with. It’s important to note that the identity field is not a 16-bit integer and thus cannot be used in the file version field directly. Finally, we want to know if the binary was built with local modifications to the working copy, which would complicate reproducing the build. As a result we append an ‘M’ to the end of the file version string if local modifications are present.

    #include "hg_version.h"
    
    #define STRINGIZE2(s) #s
    #define STRINGIZE(s) STRINGIZE2(s)
    
    #define VERSION_MAJOR               1
    #define VERSION_MINOR               0
    #define VERSION_REVISION            0
    #define VERSION_BUILD               HG_REVISION
    
    #if HG_LOCAL_MODIFICATIONS
      #define VERSION_MODIFIER "M"
    #else
      #define VERSION_MODIFIER
    #endif
    
    #define VER_FILE_DESCRIPTION_STR    HG_CHANGESET
    #define VER_FILE_VERSION            VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
    #define VER_FILE_VERSION_STR        STRINGIZE(VERSION_MAJOR)        \
                                        "." STRINGIZE(VERSION_MINOR)    \
                                        "." STRINGIZE(VERSION_REVISION) \
                                        "." STRINGIZE(VERSION_BUILD)    \
                                        VERSION_MODIFIER
    
    #define VER_PRODUCTNAME_STR         "c_hg_autoversion"
    #define VER_PRODUCT_VERSION         VER_FILE_VERSION
    #define VER_PRODUCT_VERSION_STR     VER_FILE_VERSION_STR
    
    #if LIBRARY_EXPORTS
      #define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".dll"
    #else
      #define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".exe"
    #endif
    #define VER_INTERNAL_NAME_STR       VER_ORIGINAL_FILENAME_STR
    
    #define VER_COPYRIGHT_STR           "Copyright (C) 2011"
    
    #ifdef _DEBUG
      #define VER_VER_DEBUG             VS_FF_DEBUG
    #else
      #define VER_VER_DEBUG             0
    #endif
    
    #define VER_FILEOS                  VOS_NT_WINDOWS32
    #define VER_FILEFLAGS               VER_VER_DEBUG
    
    #if LIBRARY_EXPORTS
      #define VER_FILETYPE              VFT_DLL
    #else
      #define VER_FILETYPE              VFT_APP
    #endif
    

    Step 3: Add the Pre-build Step

    Finally we need to add a pre-build step which will execute the hg_version.jse script, thus generating the hg_version.h file prior to the binary being built.

    1. Right-click on your project
    2. Select Properties
    3. Click Build Events
    4. Click Pre-Build Event
    5. In the Configuration drop-down, select All Configurations
    6. In the Command Line field, enter:
      cscript.exe hg_version.jse
    7. In the Description field, add a comment such as:
      Generate the hg_version.h file with the necessary repo identify info for versioning

    NOTE:If you have multiple projects in the same solution that all need to use the same information from Mercurial you have a few choices. One is to put the hg_version.jse script in one project which all the other projects depend on and add a link to the hg_version.h file. Another option is to create a specific version project that all it does is generate the hg_version.h file and define common version information and then have every project in the solution depends on it so it’s executed first in the build order.

    Results

    Now when each time you build your projects, the latest Mercurial information of the working copy is automatically included in the file version information.

    Version Info with Mercurial
    Version Info with Mercurial

    Final Thoughts

    So there you have it, you can now automatically include all the necessary information from your Mercurial working copy in your build to map them one-to-one with the source code that was used. In an upcoming post I’ll discuss how to do this using Subversion as your VCS.

    Other Posts in this Series

    1. Mapping Binaries in the Field to Source Code in the Repository
    2. Versioning a Native C/C++ Binary with Visual Studio
    3. Versioning a .NET Assembly with Visual Studio
    4. Integrating the Mercurial Revision into the Version Automatically with Native C/C++
    5. Integrating the Mercurial Revision into the Version Automatically with .NET
    6. Integrating the Subversion Revision into the Version Automatically with Native C/C++
    7. Integrating the Subversion Revision into the Version Automatically with .NET
  • Versioning a .NET Assembly with Visual Studio

    We’re already discussed the value of including version information in your binaries. Last post we talked about Versioning a Native C/C++ Binary with Visual Studio. This time we are going to talk about how to do this with a .NET assembly with Visual Studio. I’ll be using C# and Visual Studio 2010 but the principals work in VB .NET and other versions of Visual Studio as well.

    First of all, credit where credit is due. Many of the details below are based on this stackoverflow question.

    The source code for this post is available here.

    Step 1: It’s Already Done!

    Whenever you create a new .NET project in Visual Studio a file named AssemblyInfo.cs is created for you under the Properties folder. The annotations in the AssemblyInfo.cs file define the version characteristics include those found in the file properties. By default you’ll get a file like this which sets the copyright to Microsoft, the version to a fixed 1.0.0.0 (more on that in a moment) and a title that matches the project name.

    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    
    // General Information about an assembly is controlled through the following
    // set of attributes. Change these attribute values to modify the information
    // associated with an assembly.
    [assembly: AssemblyTitle("ClassLibrary1")]
    [assembly: AssemblyDescription("")]
    [assembly: AssemblyConfiguration("")]
    [assembly: AssemblyCompany("Microsoft")]
    [assembly: AssemblyProduct("ClassLibrary1")]
    [assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
    [assembly: AssemblyTrademark("")]
    [assembly: AssemblyCulture("")]
    
    // Setting ComVisible to false makes the types in this assembly not visible
    // to COM components.  If you need to access a type in this assembly from
    // COM, set the ComVisible attribute to true on that type.
    [assembly: ComVisible(false)]
    
    // The following GUID is for the ID of the typelib if this project is exposed to COM
    [assembly: Guid("6e0a5113-8d8a-4177-8de4-1c18b5b2c446")]
    
    // Version information for an assembly consists of the following four values:
    //
    //      Major Version
    //      Minor Version
    //      Build Number
    //      Revision
    //
    // You can specify all the values or you can default the Build and Revision Numbers
    // by using the '*' as shown below:
    // [assembly: AssemblyVersion("1.0.*")]
    [assembly: AssemblyVersion("1.0.0.0")]
    [assembly: AssemblyFileVersion("1.0.0.0")]
    

    You can make changes directly to this file however after you have several projects in the same solution, it can get rather tedious to manually update this duplicative information across all your assemblies.

    Step 2: Add a Solution-wide GlobalAssemblyInfo File for Common Info

    To make life a little simpler moving forward and in keeping with that whole DRY thing you can use a single file to hold all the assembly information that is common across multiple projects. I generally organize my source tree such that there is a top-level Code directory, with separate sub-directories for each project. Therefore I find it most convenient to place a file named GlobalAssemblyInfo.cs in the Code directory, peer to all my project directories. You can place the file wherever you want, however.

    Place common version info inside such as:

    
    // This file contains common AssemblyVersion data to be shared across all projects in this solution.
    using System.Reflection;
    
    [assembly: AssemblyCompany("Zach Burlingame")]
    [assembly: AssemblyProduct("DotNetVersionAssembly")]
    [assembly: AssemblyCopyright("Copyright © Zach Burlingame 2011")]
    [assembly: AssemblyTrademark("")]
    [assembly: AssemblyCulture("")]
    
    #if DEBUG
    [assembly: AssemblyConfiguration("Debug")]
    #else
    [assembly: AssemblyConfiguration("Release")]
    #endif
    
    // Version information for an assembly consists of the following four values:
    //
    //      Major Version
    //      Minor Version
    //      Revision
    //      Build
    //
    // You can specify all the values or you can default the Revision and Build Numbers by using the '*' as shown below:
    // [assembly: AssemblyVersion("1.0.*")]
    [assembly: AssemblyVersion("1.0.0.*")]
    //[assembly: AssemblyFileVersion("1.0.0.*")]
    

    Step 3: Add a link to the GlobalAssemblyInfo.cs file in each project

    1. In Visual Studio, right-click on a project
    2. Select Add->Existing Item
    3. Browse to GlobalAssemblyInfo.cs
    4. Select the file
    5. Click the drop-down arrow next to Add and select Add As Link
    6. Move the link to your Properties folder (optional, but keeps things neat)

    Step 4: Update the AssemblyInfo.cs for each project

    In order to avoid duplicate annotations for assembly information, you must remove entries from the AssemblyInfo.cs file that appear in the GlobalAssemblyInfo.cs file. In our example here, this is what we end up with:

    
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    
    // General Information about an assembly is controlled through the following
    // set of attributes. Change these attribute values to modify the information
    // associated with an assembly.
    [assembly: AssemblyTitle("DotNetVersionAssembly")]
    [assembly: AssemblyDescription("")]
    
    // Setting ComVisible to false makes the types in this assembly not visible
    // to COM components.  If you need to access a type in this assembly from
    // COM, set the ComVisible attribute to true on that type.
    [assembly: ComVisible(false)]
    
    // The following GUID is for the ID of the typelib if this project is exposed to COM
    [assembly: Guid("dad09178-814d-43f4-b76d-0fbe29a32544")]
    

    Step 5: Auto-incrementing the build number

    You might of noticed a couple of other changes I made in Step 3:

    // Version information for an assembly consists of the following four values:
    //
    //      Major Version
    //      Minor Version
    //      Revision
    //      Build
    //
    // You can specify all the values or you can default the Revision and Build Numbers by using the '*' as shown below:
    // [assembly: AssemblyVersion("1.0.*")]
    [assembly: AssemblyVersion("1.0.0.*")]
    //[assembly: AssemblyFileVersion("1.0.0.*")]
    

    By replacing build value with an asterisk, Visual Studio (and more specifically, MSBuild) will auto-increment that number every time you build. If you replace both the revision and the build value with a single asterisk it will cause both the revision and build number to auto-increment. This is helpful since the maximum value of any single field is 65535. By auto-incrementing both fields, the revision field is only incremented when the build value overflows, giving you in effect 4 billion unique version numbers for a given Major.Minor combination. If you overflow that, then for the love of pete increment your Major version already!

    Also notice that I commented out the AssemblyFileVersion. The differences between the AssemblyVersion and AssemblyFileVersion are discussed here. The key in our example is that you can’t use asterisks to auto-increment the AssemblyFileVersion like you can the AssemblyVersion and you probably don’t want the two getting out-of-sync (at least in this versioning scheme). By not providing an AssemblyFileVersion, MSBuild will default to using the value from the AssemblyVersion.

    Results

    Now when you build your application, all the version info above will be defined in the assembly itself. Much of this information is available directly from the Details pane of the Properties window in Explorer.

    Version Info
    Version Info

    Final Thoughts

    Note that while it is possible to auto-increment the build and revision number of the assemblies, those numbers don’t correspond to anything in source control. I’ll be discussing how to make the BUILD number automatically correspond to the revision info from the working copy of the source code using Mercurial or Subversion in an upcoming post.

    Other Posts in this Series

    1. Mapping Binaries in the Field to Source Code in the Repository
    2. Versioning a Native C/C++ Binary with Visual Studio
    3. Versioning a .NET Assembly with Visual Studio
    4. Integrating the Mercurial Revision into the Version Automatically with Native C/C++
    5. Integrating the Mercurial Revision into the Version Automatically with .NET
    6. Integrating the Subversion Revision into the Version Automatically with Native C/C++
    7. Integrating the Subversion Revision into the Version Automatically with .NET
  • Versioning a Native C/C++ Binary with Visual Studio

    Last time in  Mapping Binaries in the Field to Source Code in the Repository we talked about the value of including version information in your binaries. Today I’m going to explain how to accomplish this in Visual Studio for a native C/C++ binary. I’m using 2010 Professional, but it should work on other versions as well.

    The source code is available here.

    Step 1: Add a Version Resource

    1. Right-click on your project
    2. Select Add->Resource
    3. Select Version
    4. Click New

    This will give you two files: resource.h and <project_name>.rc. I generally rename the .rc file to be version.rc

    Step 2: Updating Version.rc

    Out of the box the version.rc file will have you define the values right there. I recommend that you instead define the values in a version.h file and use those defines in the version.rc file.

    Edit the resource file in a text editor:

    1. In the Solution Explorer, Right-click on version.rc
    2. Select Open With
    3. Select C++ Source Code Editor
    4. Scroll down to the Version section

    Here is a template Version section that I frequently use (and will build on below):

    /////////////////////////////////////////////////////////////////////////////
    //
    // Version
    //
    VS_VERSION_INFO VERSIONINFO
     FILEVERSION        VER_FILE_VERSION
     PRODUCTVERSION     VER_PRODUCT_VERSION
     FILEFLAGSMASK      0x3fL
     FILEFLAGS          VER_FILEFLAGS
     FILEOS             VER_FILEOS
     FILETYPE           VER_FILETYPE
     FILESUBTYPE        0x0L
    BEGIN
        BLOCK "StringFileInfo"
        BEGIN
            BLOCK "040904b0"
            BEGIN
                VALUE "FileDescription",  VER_FILE_DESCRIPTION_STR "\0"
                VALUE "FileVersion",      VER_FILE_VERSION_STR "\0"
                VALUE "InternalName",     VER_INTERNAL_NAME_STR "\0"
                VALUE "LegalCopyright",   VER_COPYRIGHT_STR "\0"
                VALUE "OriginalFilename", VER_ORIGINAL_FILENAME_STR "\0"
                VALUE "ProductName",      VER_PRODUCTNAME_STR
                VALUE "ProductVersion",   VER_PRODUCT_VERSION_STR "\0"
            END
        END
        BLOCK "VarFileInfo"
        BEGIN
            VALUE "Translation", 0x409, 1200
        END
    END
    

    Step 3: Adding a Version Header

    Next we create a file named version.h to provide a more convenient location to set the various version information. This is especially useful if you are sharing version information across multiple projects in a single solution. Here’s the information I generally start with mine:

    
    #define STRINGIZE2(s) #s
    #define STRINGIZE(s) STRINGIZE2(s)
    
    #define VERSION_MAJOR               1
    #define VERSION_MINOR               0
    #define VERSION_REVISION            0
    #define VERSION_BUILD               0
    
    #define VER_FILE_DESCRIPTION_STR    "Description"
    #define VER_FILE_VERSION            VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD
    #define VER_FILE_VERSION_STR        STRINGIZE(VERSION_MAJOR)        \
                                        "." STRINGIZE(VERSION_MINOR)    \
                                        "." STRINGIZE(VERSION_REVISION) \
                                        "." STRINGIZE(VERSION_BUILD)    \
    
    #define VER_PRODUCTNAME_STR         "c_version_binary"
    #define VER_PRODUCT_VERSION         VER_FILE_VERSION
    #define VER_PRODUCT_VERSION_STR     VER_FILE_VERSION_STR
    #define VER_ORIGINAL_FILENAME_STR   VER_PRODUCTNAME_STR ".exe"
    #define VER_INTERNAL_NAME_STR       VER_ORIGINAL_FILENAME_STR
    #define VER_COPYRIGHT_STR           "Copyright (C) 2011"
    
    #ifdef _DEBUG
      #define VER_VER_DEBUG             VS_FF_DEBUG
    #else
      #define VER_VER_DEBUG             0
    #endif
    
    #define VER_FILEOS                  VOS_NT_WINDOWS32
    #define VER_FILEFLAGS               VER_VER_DEBUG
    #define VER_FILETYPE                VFT_APP
    

    Step 4: Add the Necessary Include

    The final step is to add the necessary include line to the version.rc file for the version.h file:

    // Microsoft Visual C++ generated resource script.
    //
    #include "resource.h"
    #include "version.h"
    
    #define APSTUDIO_READONLY_SYMBOLS
    

    Results

    Now when you build your application, all the version info above will be defined in the binary itself. Much of this information is available directly from the Details pane of the Properties window in Explorer.

    Version Info
    Version Info

    Final Thoughts

    Note that this information is static from build to build. You must change the version numbering yourself or use a script to auto-increment values. I’ll be discussing how to make the BUILD number automatically correspond to the revision info from the working copy of the source code using Mercurial or Subversion in an upcoming post.

    Other Posts in this Series

    1. Mapping Binaries in the Field to Source Code in the Repository
    2. Versioning a Native C/C++ Binary with Visual Studio
    3. Versioning a .NET Assembly with Visual Studio
    4. Integrating the Mercurial Revision into the Version Automatically with Native C/C++
    5. Integrating the Mercurial Revision into the Version Automatically with .NET
    6. Integrating the Subversion Revision into the Version Automatically with Native C/C++
    7. Integrating the Subversion Revision into the Version Automatically with .NET
  • Mapping Binaries in the Field to Source Code in the Repository

    The Scenario

    Andrew from customer support walks down to your cubicle (wait, you have an office?! jealous.) and tells you that he has Joanne on the line from Widgets and Wrenches Unlimited. She says that your remote login software is crashing and they can’t access the server that controls the CNC machine which means they can’t make tools. One of the first things you are going to want to know, is “What version of the app are you running?”

    Usually if it’s a product or mature application, there will be a straightforward way to get this information – an About page or the version name right in the application shortcut for instance. When it’s a smaller app or library, or when you need more specific information than “v1.2”  though, you might be up a creek. Numerous times I’ve run into this problem on an internal application where there is no installer, about page, or any other information on the version of the binary I’m looking at and what it’s origins might be.  Sometimes it’s as simple as “let’s just grab the latest version and try that”, but other times that’s not an option. My solution to this problem on many projects has been to include the version information in the binary or assembly itself. At the very least someone can view the Details tab on the Properties window in Explorer and get the info directly.  Best of all it works on all versions of Windows, even if the application won’t run.

    A Solution

    There are tons of different versioning schemes out there, but I tend to favor:

    MAJOR.MINOR.REVISION.BUILD

    Three things have been key for making this work for me:

    1. Make the least significant number (BUILD in my example above) correspond to the revision number from the source control repository.
    2. Note if the binary was built from a working copy with local modifications
    3. Make it happen automatically.

    With these three things, we can take a binary and know exactly what revision we need to grab from source control to reproduce the problem. Before we release a binary to anyone, we can make sure it wasn’t built with local modifications (and thus potentially seriously complicating reproducing the problem). And since it all happens automatically, we don’t have to remember jump through any hoops. Yay!

    How-To

    The basic concept is that a pre-build step runs which grabs the version information from the source control tool for the working copy and generates an file which is included in our project. From there we include the information into our version scheme and then it’s just applied to a normal resource version file or AssemblyInfo.cs.

    Another policy I try follow on my projects is having everything build on checkout with as minimal a development environment as possible (usually just Visual Studio and the source control tools). To that end, I try to avoid bringing a scripting engine like Python into the development environment just to allow a simple build script. So to accomplish that pre-build step, I use the Javascript engine for the Windows Script Host (WSH) which is built-in since Windows 98.

    Over the next several posts, I’m going to explain how to accomplish this in Visual Studio. I’ll explain how to do it for a native C/C++ binary and a C# assembly as well as automating the BUILD number from Subversion and Mercurial.

    Other Posts in this Series

    1. Mapping Binaries in the Field to Source Code in the Repository
    2. Versioning a Native C/C++ Binary with Visual Studio
    3. Versioning a .NET Assembly with Visual Studio
    4. Integrating the Mercurial Revision into the Version Automatically with Native C/C++
    5. Integrating the Mercurial Revision into the Version Automatically with .NET
    6. Integrating the Subversion Revision into the Version Automatically with Native C/C++
    7. Integrating the Subversion Revision into the Version Automatically with .NET