So you’ve got yourself a nice, shiny, new TFS 2010 server and you’re using its build automation features to build your .NET code but you also have some, shall we say it, “legacy” VB6 code laying around that you have to keep alive.  You’ve retired source safe and installed the MSSCCI provider TFS 2010 so TFS is your source repository but now you want the build server to build your VB6 code just like it does for your .NET code.

Here’s how to get VB6 applications built using TFS 2010:

Preliminary Steps

1. Go to your build templates folder in source control and make a copy of DefaultTemplate.xaml.  Call it VB6BuildTemplate or something similarly memorable.

2. Open up the new template and find the “Compile the Project” activity sequence.  For reference it’s roughly located in “Compile, Test and Associate Changesets and Work Items” > “Compile and Test” > “Compile and Test for Configuration” > “If BuildSettings.HasProjectsToBuild” > “Compile the Project”

3. Find the “Run MSBuild for Project” activity and delete it.  We’re going to replace that with our own tasks.

Ensure the Output Directory Exists

When you that MSBuild activity runs to compile your .NET projects the output locations are created for you automatically but since we’re not using MSBuild we don’t have that luxury for our VB6 compilations so we have to create the folder ourselves.

Start by dragging an “If” Activity into the sequence

image

Then drag a CreateDirectory task (from Team Foundation Build Activities) into the “Then” section as shown

image

Now the point of this is to check if the outputDirectory has already been created and to create it if it hasn’t.

Set the Condition for the If Activity to: Not System.IO.Directory.Exists(outputDirectory).

Set the Diirectory property of the createDirectory to outputDirectory

image

For maintainability, rename the activities in the designer as well so that you can better understand what is happening.

image

By the way, if you are sure the directory doesn’t get created earlier in your process then you can drop the if activity and just place the createDirectory activity into the flow directly.

Ensure a Log Directory Exists

When we run the VB6 compiler in a build we need to capture the log output to a text file otherwise VB will want to try and open a dialog box telling us there was a compiler problem and want us to click OK. Unfortunately when running unattended, there is no UI and we will never see a window to click the link on.

We’re going to place our log file output in the drop location so that we can easily access it once the build is complete.

Create another if task (or copy/paste) from the previous step and ensure that we use logFileDropLocation instead of outputDirectory.

image

Call the VB6 Compiler

Now drag an InvokeProcess activity into the workflow and set it up as follows:

DisplayName VB6 Compiler
FileName Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + "\Microsoft Visual Studio\VB98\VB6.exe"
Arguments "/make """ + localProject + """ /out """ + logFileDropLocation + "\vb6.log"" /outdir """ + outputDirectory + """"
Result VB6Result

 

Note that the VB6Result variable will likely to show up with a warning until you create it as a variable in your workflow. So on the workflow create the variable with a type of Int32 and a scope of “Compile the Project”

If you wish, you can also send stdOutput and errOutput from the InvokeProcess tasks to the build log using the WriteBuildMessage and WriteBuildWarning tasks.  For each of these use the appropriate std/errOutput variables as the values for the Message property, though with the VB6 compiler you’re unlikely to see any messages since we’re sending output to the log file.

The workflow should now look something like this:

image

Check the Compiler Result

Finally we need to check if the compile passed or not.  If it fails we will get a non-zero result back from InvokeProcess

If we don’t check this then the build process just assumes things work and continues on it’s merry way. so add another “If” Activity to the flow and in the Then part add a “Throw” Activity from the Error Handling group.  Set the Throw Activity’s Exception property to “New Exception” and the Condition on the “If” activity to “VB6Result <> 0”.

image

Don’t forget to rename the activities to help you diagnose any problems.

Use It in a Build

Finally, save your workflow, check it in to source control (in the BuildProcessTemplates folder) and then create a build definition using the new template.

Trigger the build and check the compilation results.  Everything should now work as expected.  Now all you need to do it retire that VB6 code :-)  Good luck with that!