Build your old VB6 projects with TFS 2012

or How to edit a TFS 2012 build process template

A few weeks ago, I blogged about using VB6 with TFS 2012. The build process I proposed was relying on a MSBuild script that you had to check-in into TFS. This script was responsible for calling VB6 on the command line and generate your VB executables. I just felt like something was left unexplored here, and I wanted to provide a little bit more sophisticated alternative for building your VB6 apps. So let’s customize the build workflow for the sake of our VB6 projects!

This post is also a tutorial for editing a TFS 2012 build process template!

The plan

We will modify the Default Template in order to make it compatible with VB6 projects. In the Solutions to Build process parameter, we want be pass a list of .NET solutions (.sln files), but also .vbp files. We will rely on some external activities to invoke VB6 compilation commands.

We’ll try to support the Ouputs clean option of regular builds, because it is useful for continuous Integration.

Set up your environment

We’ll be using the latest Community Build Extensions, you may download them and place the appropriate binaries in the custom assemblies folder that you have configured in your controller. If you don’t know about what I’m talking about, check out my A small guide to edit your TFS 2012 build templates and I hope you’ll be sorted.

Duplicate the Default Template, rename it something like DefaultTemplateVb6. If you want to be able to edit both files at once, follow this procedure I wrote that will avoid unwanted compile errors.

Build process changes

Open your build process template and go to Run On Agent => Try Compile, Test, and Associate Changesets and Work Items. Now look for the Try to Compile the Project TryCatch activity, you should double-click on its icon to “focus” the Workflow edition on this subcontent – it’s just more comfortable.

We are here at the heart of the loop that calls MSBuild on every project to build. We will need to store the result of the last VB6 compilation. For this, we need a variable in the scope of the Compile the Project block. Add a vbReturnCode variable as follows:


We want to run MSBuild on regular projects, and launch VB6 on .vbp projects. So we’ll add an If activity in order to filter VB6 projects. Insert it just before the Run MSBuild for Project activity.

Add a Sequence in the Then block, and drag the existing MSBuild activity in the Else block. Actually, recreate following piece of workflow:


Remember to add the custom activities in the toolbox in order to use them in the workflow (right-click and Choose Items…).


  • If “If Project Is VB6”
    • Condition: localProject.EndsWith(“.vbp”, StringComparison.InvariantCultureIgnoreCase) Or localProject.EndsWith(“.vbg”, StringComparison.InvariantCultureIgnoreCase)
    • Then
      • Sequence “Process VB6 Project”
        • VB6
          • see picture below for parameters
        • If “If VB Return Code” (see picture below)
          • Condition : vbReturnCode = 0
          • Then
            • SetBuildProperties “Set Compilation Status to Suceeded”
              • PropertiesToSet : CompilationStatus
              • CompilationStatus : BuildPhaseStatus.Suceeded
          • Else
            • SetBuildProperties “Set Compilation Status to Failed”
              • PropertiesToSet : CompilationStatus
              • CompilationStatus : BuildPhaseStatus.Failed
    • Else
      • move there the existing MSBuild activity


Now here is the content of the If block:


And the VB6 activity parameters:



Check-in the whole thing and check it compiles on a single solution.

Cleaning projects

In order to support the partial clean of builds (Clean Workspace is set to Output), we have to filter the VB6 projects from the process. VB6 executables are produced directly in the BinariesFolder, which is emptied automatically. The following actions will prevent nasty errors when cleaning outputs (because our .vbp aren’t MSBuild files).

First, navigate to Run On Agent => Initialize Workspace, look for the “Clean Project” Sequence, then encapsulate the If File.Exists(Project) with the same filter as we did previously:



The full condition text is:

Not localBuildProjectItem.EndsWith(".vbp", StringComparison.InvariantCultureIgnoreCase) And Not localBuildProjectItem.EndsWith(".vbg", StringComparison.InvariantCultureIgnoreCase)


Finally, set the process parameter Solution Specific Build Outputs to True to avoid a big mess in the Drop folder. And voilà, you can now mix and build regular solutions or VB6 projects with the same build definition! Smile


Above is what I obtain in the Drop folder, enjoy your builds!

Small guide to using VB6 with TFS 2012

I’ve been recently working for a client with lots of VB6 projects. The fun part is that we wanted to migrate from VSS to TFS 2012. Although VB6 no longer supported by Microsoft, there is no reason why TFS would not work for VB6, you can host Java in TFS right? If you have VB6 projects and want to plug them into TFS and have them built in a continuous integration perspective, then I hope this small guide will be helping you.

What to install

First, check you have VB6 with SP6, and the mouse wheel fix as well, I won’t spend more time here since you’re already using it.

You’ll need to install the Visual Studio 2012 edition of your choice, with the latest Update (at this time it is Update 2). Then the famous TFS Power Tools, which add nice check-in policies (and more). Finally, you’ll need the MSSCCI Provider for Visual Studio 2012, 32-bit version or 64-bit version.

After installation check: verify that inside VS 2012 => TOOLS => Options => Source Control, the Plug-in Selection value is set as follows:


If you still have Visual SourceSafe around

Warning, the MSSCCI provider has rerouted VB6 source control interactions to the Team Foundation Server source controller. To connect back to VSS, you need to perform some registry operations. Fortunately, small utilities will do that for you, by listing all MSSCCI providers available on your machine, and allowing you to choose which one is active. So you’ll be able to switch back and forth easily from VSS to TFS. This one worked for me => SCPSelector.exe.


SCPSelector in action


Unwanted prettify options for VB6

Visual Studio 2012 *doesn’t know* about VB6, it knows about VB.NET!

When you are merging files, you don’t want VS 2012 to make assumptions regarding your syntax, and even less *modify your VB6 code*. Make sure you uncheck those options in the TOOLS => Options => Text Editor => Basic => VB Specific menu:


How to map the sources

Local workspaces are great, but the MSSCCI provider is not happy with them. You’ll have to use the traditional server workspaces. Well, it’s not a big deal.

Ok, so let’s create server workspaces and map our VB6 sources from TFS. Now, I want to develop with VB6 but when I open the project with VB6, I get asked to add my project to TFS, doh! Actually, I’d want me and my users to open up any VB6 project as smoothly as possible. To achieve that, you have to edit the MSSCCPRJ.SCC files (or create them), they contain the necessary MSSCCI data to connect to the proper source controller. The bad news is that you can’t share those files! They are specific to your login and your workspace so adding them into the source controller is useless! Sad smile


VbTfsBinding will do the work for you

I wrote a small utility that will generate all those files for you. Copy it at the root of your workspace and it will generate a MSSCCPRJ.SCC file for every .vbp file in your workspace. Now you can just open any VB6 project in your workspace, you should not be annoyed by any configuration message box. 

Here you are with the source code, and the executable (use it at your own risks of course).

So here’s a few tips for using VbTfsBinding:

  • Configure the config file with your TFS Project Collection URL
  • To share the tool, you can include it in your TFS source controller, in a subfolder at the root of your workspace (or branch), and add a .cmd file that changes the current directory and launches “VbTfsBinding.exe /force”
  • The /force flag will overwrite read-only files, in case someone checks-in a MSSCCPRJ.SCC file

Ok, now the basic source control feature of TFS are usable directly from VB6, but I would advise to always check-in from VS 2012. This just allows you to make sure you don’t forget files in your changesets, you can check all your pending changes with a glance, and I feel more secure that way.

Building your VB6 executables

Now the fun part. Our goal is to call VB6 on as many VB6 projects we want to build. The command line is:

Vb6.exe /m Projects.vbg /out Projects.vblog

Where projects.vbg is project group file which contains the list of projects we want to build.

Let’s follow the path of the Lazy. Let’s use a simple MsBuild .proj file to encapsulate the VB6 compilation logic, and rely on the default DefaultTemplate.xaml of TFS do the rest.

First, prepare your VB6 group file and check it next to your projects in the source controller (paths are relative). You can check the compilation with VB6 on your machine.

Then, add the following MsBuild file next to the .proj file, let’s call it Projects.proj:

<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="">

    <VBPath>C:\Program Files\Microsoft Visual Studio\VB98\VB6.exe</VBPath>
    <VBPath Condition="Exists('C:\Program Files (x86)\Microsoft Visual Studio\VB98\VB6.exe')">C:\Program Files (x86)\Microsoft Visual Studio\VB98\VB6.exe</VBPath>

  <Target Name="Build">
    <Exec ContinueOnError="True" Command='"$(VBPath)" /m Projects.vbg /out Projects.vblog"'>
      <Output TaskParameter="ExitCode" PropertyName="VBExitCode"/>

    <Message Text="---- Start VB Output ------------------------------------------------------------" />
    <Exec ContinueOnError="True" Command="type Projects.vblog" />
    <Message Text="---- End of VB Output -----------------------------------------------------------" />
    <Error Condition="'$(VBExitCode)' != '0'" Text="Fatal error because of VB exit code." />
      <VBBinaries Include="**\*.exe" />
    <Copy Condition="'$(OutDir)' != ''" SourceFiles="@(VBBinaries)" DestinationFolder="$(OutDir)" />
  <Target Name="Clean">
      <VBBinaries Include="**\*.exe" />
    <Delete Files="Projects.vblog" />
    <Delete Files="@(VBBinaries)" />

Now, create a new build definition, based on the Detault Template, make sure you have a Drop folder location, then the process parameters as follows (transposing the .proj file path to yours):


The nice thing is that this build is actually pretty standard: it is a build workflow that calls MsBuild for compilation, so there is naturally an MsBuild log file in the build Summary:


You’ll find your VB6 applications in the Drop Folder:


It’s up to you to set this build as a continuous integration build, or to schedule it, you know, it’s just a TFS build Winking smile 

Do you feel any better than with VSS? Enjoy! Smile