Thursday, March 10, 2011

Publishing .NET Applications

This is a problem I came across in my previous job at Fairfax Digital, when setting up automated builds; now that I am working at TouchStar, I’m facing the same problem, but couldn’t remember what I did the first time round.

The problem is this: when building ASP.NET web applications using TFS or some other continuous integration solution (I’m using UppercuT at TouchStar), the MSBuild engine very conveniently creates a _PublishedWebsites folder in your output folder, and then creates a subfolder in that folder for each website that you are creating. So far, so good. However, when building executable applications, such as console apps, WPF applications or Windows services (and I’m building all three at TouchStar) then it just throws everything into one directory, and leaves it to you to pick out the bits you need. “If only you could export your build results to a _PublishedApplications folder!”, I hear you cry.

Well, that’s essentially my solution. I took a copy of the Microsoft.WebApplication.targets file that is referenced in the ASP.NET project file, renamed it to Microsoft.Application.targets and saved it to C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Applications. I then tweaked it, renaming variables and such to match the type of content, and removing any references to /bin folders. I then reference the new file in the Visual Studio project file by adding the following line:

  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Applications\Microsoft.Application.targets" />

And voila! I now have one folder per application in the _PublishedApplications folder when run as part of an automated build. If I build from within Visual Studio, outputs are still sent to their usual location (e.g. /bin/Debug/). I’ve included a link to the file below.

[Download Microsoft.Application.targets]


Unknown said...

That's actually pretty hot!

PoorInRichfield said...

Unfortunately, this solution has one small bug. When building non web applications, the App.config file is not copied into the appropriate _PublishedApplications folder.

The reason appears to be due to the removal of all reference to the /bin folder from the .targets file. The App.config file (which always gets renamed on a build to match the .exe name) doesn't get copied to the /obj folder during a build, which is where the modified .target file instructs MSBuild to get it's files from.

Unfortunately, I haven't figured-out a solution to this yet.

PoorInRichfield said...

One small problem with this approach...

For non web applications, the App.config gets renamed to match the name of the executable. For some add reason, the .config doesn't get copied into the _PublishedApplications folder.

The modified .target file relies on files in the /obj folder to move into the _PublishedApplications folder, but the .config file doesn't get copied into the /obj folder. So, I'm at a loss as to how to fix this issue.

David Keaveny said...

Not a solution really, but more of a workaround - I use Uppercut to manage my builds, since it handles multiple build environments nicely, and I have an extra task in there to copy the correct configuration file into the output folder.

I would be interested to know if anyone can come up with an actual fix for this though.