TeamCity + WiX + MSBuild workflow suggestions need

2019-03-30 11:09发布

问题:

I've been working on the next step of my continuous integration project, which is to get TeamCity to build my application, automatically change the version number of all assemblies, and then create an installer.

A little background first:

I've been running TeamCity successfully for the past several months, and it builds my configurations and runs my NUnit and NCover tests just fine.

I took a little time researching installers -- I have always hated InstallShield and never considered it for my current application. I like NSIS, but then happened to come across WiX. I don't have any intimate knowledge of the MS Installer architecture, which I understand is dangerous for complicated projects, so at some point I'll need to learn more about it. However, after a few days of wading through SO questions, googling, and reading blogs, I have a WiX project that successfully builds, installs, the application runs, and everything uninstalls cleanly. Great!

I also wanted to have the TeamCity build configuration automatically update the version number of all of my assemblies. I was able to mock up this functionality by installing the MSBuild Community Tasks on my development machine, and creating a Deployment configuration that uses a BeforeBuild target and the FileUpdate task to change the version number. That works properly, except that on my development machine, I don't have a build_vcs_number_1 environment variable to substitute.

So that's where I am now -- I need to have TeamCity do the update, and while it does have the build_vcs_number_1 environment variable, I can't figure out how to get at the WiX MSBuild Community Tasks.

One post I read recommended checking in the MSBuild targets into an SVN folder. I have an /extlib folder for things like this, so my TeamCity VCS checkout rules look something like this:

+:tags/2010-10-15=>src
+:extlib=>extlib

How do I get to extlib from an environment variable? When I run the build, TeamCity complains (and correctly so) that it can't find c:\wix30\MSBuildCommunityTasks. The actual folder is C:\TeamCity\buildAgent\work\3e073d2b74226378\extlib\wix30\MSBuildCommunityTasks. The folder is auto-generated since I'm doing a server-side checkout, so there must be some environment variable that TeamCity sets that I can use to get the correct path.

One thing I should note is that I've gone into the build configuration -> Properties and Environment Variables and found the unintuitive droplist with all existing variables, and didn't see anything that sounded like a variable that points to the work path.

One possible workaround I can think of is to just install MSBuild Community Tasks on the build server, and then I can create a system environment variable that can be accessed by <WixToolPath>.

Does anyone have other suggestions?

回答1:

I can see some merit in trying to have the msbuild community tasks in SVN (to reduce the requirements of a build machine) but personally I'd just install them on the server. Important part: update your documentation for your build server to list installing that as a pre-requisite. For me, I use the community tasks in basically every msbuild across several projects, and deployment scripts, so keeping them all in SVN is a bit redundant. I also have WiX installed on the build server.

I do something similar, but rather than a before build target, I have an msbuild project file roughly like this:

<Target Name="Build">
    <CallTarget Targets="UpdateVersionNumbers"/>
    <MSBuild Projects="Project.sln" Targets="Build"/>
</Target>

My UpdateVersionNumbers target grabs the SVN revision, and then uses a regex and FileUpdate task to change the 4th part of the version number to the SVN revision.

Then I run the normal build of the solution file, and included in that it builds the .wixproj. Pretty simple, really.


To answer some of your other questions though:

  • When specifying paths, always use paths relative to the root of your solution (checkout dir). So eg in this case, you'd just use wix30\MSBuildCommunityTasks. TeamCity executes msbuild with the working dir as the root, and on top of that, it doesn't matter where you or other developers do their checkout to - the paths are all just relative.
  • You can pass parameters in teamcity to msbuild using the Build Parameters -> System properties. So eg, add a property called agentHome that has a value of %system.agent.home.dir% and then you can reference it in your msbuild file as $(agentHome). Note if you're also invoking msbuild again as in my example above, you'd have to do:

      <MSBuild Projects="Project.sln" Properties="agentHome=$(agentHome)" Targets="Build"/>
    

    to actually pass that variable into Project.sln. I think but I'm not positive that msbuild running on a .sln file will also pass all the properties to all the individual projects, so you can actually access it in your before build event.


Side note on installers (I recently went through the same thing you did): I settled on WiX 3.0, and though there's quite the learning curve to it, it works well. We started a new stream of development, and started using VS2010 and .NET 4. Well, WiX 3.0 is not compatible with VS2010, so we needed WiX 3.5 (which is still in Beta - though the state of it seems much better now than it was a few months ago, but they are still lagging. Such is the nature of open source, sometimes). I had some pain getting WiX 3.0 and 3.5 to install together, but did finally figure it out.

The frustration of this though (between incompatibility, flaky betas (from a few months ago), and the overall slow progress) really turned me off WiX (no offense to the guys working on WiX, but I just want an installer and I don't want to get that involved. Note, they are very frustrated too). Add to that the product I need it for next requires a much more complex installer, and WiX just seems like way too much work. I just built up my installer using AdvancedInstaller, and it only took a couple days, and so far has been working well (though we're just in early dev stages now, but starting continuous deployment and testing). AI's pricing is reasonable (we're still in trial version now) but I'll be buying in the next couple days.

I'm SURE the time I spent learning AI was MUCH less than I'd spend learning WiX, and then trying to make it do everything I need. It is a bit unavoidable to learn SOMETHING about how Windows Installer works, but you don't have to get too in-depth.



回答2:

I hate it when this happens... type a long question, only to find something that I missed minutes later.

I wonder if this is it:

I guess my question now is -- can I actually use %system.agent.work.dir% in my .wixproj? I'll try it now.