Hey, it’s been a while! The usual #lifegetsintheway excuses all apply, but you knew that right? Fear not though, treasured reader, for today we are going to delve into the adrenaline-filled world of MsBuild/TFS interaction!
But Why?
There are plenty of reasons for wanting to interact with your TFS server from MsBuild. Maybe you want to ensure that you always get the latest version of a referenced DLL on each build? You could need to update a source-controlled log file when a certain configuration is built on your continuous integration machine? All of these sorts of things are possible and I’ll be going over some of the more complex scenarios in future articles. For now though I want to fix a bit of an annoyance with the web or service installers I went through in previous posts. If you haven’t worked through these don’t worry, you can get the finished source for the service installer here: WixServiceInstallerExample.zip (184.90kb). (You will need WiX installed, but that is a good thing)
Lets Go
Lets start by recreating the problem; step one is to add the service installer solution to source control and check everything in. Once done, try to build the installer project. Oh no!
Unable to execute transformation. Access to the path ‘……..’ is denied.
What is happening here? The installer build process needs write access to the file WixServiceInstallerExample.wxs, which is denied because it is currently checked in. You can verify this by checking the file out and building again, which will work. So all we need to do is make this automatic.
Open up the project file for the installer (right click > Unload project, right click > Edit WixServiceInstaller.wixproj). Add the following three properties to the top PropertyGroup element:
<TfsExeLocation>$(Vs110ComnTools)..\IDE\tf.exe</TfsExeLocation>
<CheckinComment>Checkin for installer build.</CheckinComment>
<CheckinOverrideReason>Checkin for new installer build.</CheckinOverrideReason>
The first item is the path to the ft.exe file on your computer. Unfortunately we have to do all of this stuff using the command line! The nice thing about defining it here though is that if you have a wacky install on your build box like I had to deal with for one client, causing the TFS build to break, you can override this property in your TFS build definition. If you are using VS2010 then use Vs100ComnTools instead.
The other two items are there for when we check the file back in again, ensuring we don’t get any policy blocks on checkins.
Now, right at the beginning of the BeforeBuild target at the bottom of the file, add this line:
<Exec Command=""$(TfsExeLocation)" checkout %(ProjectReference.Filename).wxs"
Condition="'%(ProjectReference.ContentProject)'=='True'" />
The Exec command is deliciously powerful; suddenly the power of any command-line tool you can find or build is at your beck and call. There really isn’t a huge amount to this; we pass a ‘checkout’ command and the path to the wxs file to the ef.exe command. Next add the following right at the end of the BeforeBuild target:
<Exec Command=""$(TfsExeLocation)" checkin %(ProjectReference.Filename).wxs
/comment:"$(CheckinComment)" /noprompt
/override:"$(CheckinOverrideReason)""
Condition="'%(ProjectReference.ContentProject)'=='True'" />
This time we’re checking the file in. It’s a pretty similar command to the last one but we are just passing a few more arguments specifying comments and policy override reasons to be stored next to the checkin. The noprompt option tells tf.exe not to pop up any dialogs etc.
Check out the show!
That was easy huh? You can go ahead and reload the project now. Make sure all files are checked in and run the build. Keep watching the solution explorer window and you should see the wxs file’s icon changing to checked out, and back to checked in as the build progresses. Happy days.
Limitations
Just bear in mind that this code is always run when you build. That means that even if the wxs file is checked out before you build, it will end up checked in afterwards.
Hopefully this post will have been of use to someone, but I’m off to get started on the Christmas celebrations. Merry Christmas to those of you who celebrate it!
Did you find this post useful or interesting? I'd be really grateful if you could return the favour by clicking this google link: