<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>Tentacle Software Blog</title>
        <link>http://blog.tentaclesoftware.com/Default.aspx</link>
        <description>Tentacle Software developer blog for Sam Wood, Windows Home Server MVP</description>
        <language>en-NZ</language>
        <copyright>Sam Wood</copyright>
        <generator>Subtext Version 2.5.1.20</generator>
        <image>
            <title>Tentacle Software Blog</title>
            <url>http://blog.tentaclesoftware.com/images/RSS2Image.gif</url>
            <link>http://blog.tentaclesoftware.com/Default.aspx</link>
            <width>77</width>
            <height>60</height>
        </image>
        <item>
            <title>Automating Windows Server Solutions Add-In Package (*.wssx) Builds to Support In-Place Upgrades</title>
            <category>Development</category>
            <category>WSSX</category>
            <category>Windows Home Server</category>
            <link>http://blog.tentaclesoftware.com/archive/2011/07/01/automating-windows-server-solutions-add-in-package-wssx-builds-to.aspx</link>
            <description>&lt;p&gt;The Windows Server Solutions SDK gives us some great new functionality for deploying Add-In packages: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;A proper upgrade process &lt;/li&gt;    &lt;li&gt;Signing &lt;/li&gt;    &lt;li&gt;Client installers that can be automatically applied to any joined PCs &lt;/li&gt;    &lt;li&gt;EULA support &lt;/li&gt;    &lt;li&gt;Localization support &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;But, because there’s no such thing as a free lunch, the new functions come with added complexity. As I’ve &lt;a href="/archive/2011/05/31/whs-2011-add-in-deployment-package-upgrades.aspx"&gt;discussed previously&lt;/a&gt;, in order for your Add-In to support in-place upgrades there are a bunch of properties that need to be changed whenever you build a new version of your Add-In:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Package Version in AddIn.xml &lt;/li&gt;    &lt;li&gt;ServerBinary File Version in AddIn.xml &lt;/li&gt;    &lt;li&gt;Product Version in your installer project (&amp;lt;product&amp;gt;.wxs if you’re using WiX) &lt;/li&gt;    &lt;li&gt;Assembly File Version and Assembly Version in AssemblyInfo.cs for any changed assemblies &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;It’s really easy to forget one of those and break the upgrade process. So, how do we take the pain away?&lt;/p&gt;  &lt;p&gt;What follows is my solution for build automation with WSSX files. This is only what works for me, and there are certainly other ways to accomplish the same thing, so feel free to offer your methods in the comments below. &lt;/p&gt;  &lt;p&gt;This is going to be a long one so go grab a coffee!&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;Note: &lt;/strong&gt;As always, don’t use any GUIDs from my sample code in your projects. Create your own using Tools –&amp;gt; Create GUID in Visual Studio.&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;Overview&lt;/h3&gt;  &lt;h4&gt;Goals&lt;/h4&gt;  &lt;p&gt;I have two major goals for this automation process:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Automatically build a valid WSSX package whenever I build my Add-In solution in Visual Studio &lt;/li&gt;    &lt;li&gt;Automatically support in-place upgrades for my Add-In &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The first one is easy; &lt;a href="http://msdn.microsoft.com/en-us/library/gg513966.aspx" target="_blank"&gt;run makecab.exe with the appropriate metadata files&lt;/a&gt; in a post-build target and we’re set. If we want to continue to use the old Windows Home Server v1 “upgrade” model, which means forcing our users to manually uninstall previous versions of our Add-In before installing the latest, then we don’t need to go any further. Can you tell I think that’s a bad idea?&lt;/p&gt;  &lt;p&gt;A much better plan is to allow our users to install the new version of our Add-In without worrying about prior installs; the install process is a key first impression we make with our users, and they’ll judge our product harshly if the install experience is crap. &lt;/p&gt;  &lt;p&gt;So, our second goal is where the magic happens, and what this post is all about; allowing hassle-free (for the user and for us) in-place upgrades.&lt;/p&gt;  &lt;h4&gt;Dependencies&lt;/h4&gt;  &lt;p&gt;I rely heavily on &lt;a href="http://en.wikipedia.org/wiki/MSBuild" target="_blank"&gt;MSBuild&lt;/a&gt;, &lt;a href="http://wix.sourceforge.net/" target="_blank"&gt;WiX v3.5&lt;/a&gt;, &lt;a href="http://autobuildversion.codeplex.com/" target="_blank"&gt;Build Version Increment Add-In&lt;/a&gt; for Visual Studio, and our &lt;a href="/archive/2011/06/24/windows-server-solutions-add-in-package-project-wssx-for-visual.aspx"&gt;WSSX project for Visual Studio 2010&lt;/a&gt;. I’m going to assume you’ve had some experience with MSBuild and editing project files.&lt;/p&gt;  &lt;p&gt;To follow my process you’ll need to install these Visual Studio extensions:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://autobuildversion.codeplex.com/" target="_blank"&gt;Build Version Increment Add-In for Visual Studio&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://visualstudiogallery.msdn.microsoft.com/55bd7010-ca1f-4995-8374-82fec48f1d13" target="_blank"&gt;Windows Server Solutions Add-In Package Project for Visual Studio 2010&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://wix.codeplex.com/releases/view/60102" target="_blank"&gt;WiX Toolset v3.5&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Unfortunately, the WSSX project doesn’t work with Visual Studio Express. You’ll need Visual Studio 2010 Professional or higher.&lt;/p&gt;  &lt;p&gt;If you’re not using WiX to build your installers you’ll need to customize the MSBuild targets I’ll show you below. I don’t have any experience with other Windows Installer builders, so you’re on your own there!&lt;/p&gt;  &lt;h4&gt;Sample Solution&lt;/h4&gt;  &lt;p&gt;I’ve put together a &lt;a href="http://www.tentaclesoftware.com/download/WssxPackageExample.zip" target="_blank"&gt;sample Visual Studio 2010 solution&lt;/a&gt; that demonstrates everything we’re going to walk through below. You’ll need to:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Download and install the dependencies above &lt;/li&gt;    &lt;li&gt;Download and extract the &lt;a href="http://www.tentaclesoftware.com/download/WssxPackageExample.zip" target="_blank"&gt;sample automated build solution&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Reference&lt;em&gt; Microsoft.windowsserversolutions.administration.objectmodel.dll&lt;/em&gt; from the &lt;a href="http://www.microsoft.com/download/en/details.aspx?id=11140" target="_blank"&gt;Windows Server Solutions SDK&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;To give you a navigation reference, this is what Solution Explorer looks like in the sample solution:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;WssxPackageExample&lt;/strong&gt; is our Dashboard Add-In assembly &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;WssxPackageExample.AddIn&lt;/strong&gt; is our WSSX project that will build the final *.wssx file, and contains our AddIn.xml metadata file &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;WssxPackageExample.Client32&lt;/strong&gt; is the installer for our (fake) client component &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;WssxPackageExample.Client64&lt;/strong&gt; is the installer for our (fake) 64-bit client component &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;WssxPackageExample.Server&lt;/strong&gt; is the installer for our (real) Dashboard Add-in &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a href="http://blog.tentaclesoftware.com/images/blog_tentaclesoftware_com/Windows-Live-Writer/Automating_9BD7/image_15.png" rel="lightbox"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.tentaclesoftware.com/images/blog_tentaclesoftware_com/Windows-Live-Writer/Automating_9BD7/image_thumb_6.png" width="322" height="275" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The sample solution actually builds and can be deployed to your test server and the Dashboard Add-In will load. The “fake” client installers will install on any joined PCs, but they don’t actually create any files (we just create a directory tree).&lt;/p&gt;  &lt;h4&gt;High-level Process&lt;/h4&gt;  &lt;p&gt;The automation process is driven from the bottom up. The idea is that any change to the project causes a chain of version updates that will ensure that the final *.wssx output will work as an in-place upgrade for existing installations of our Add-In.&lt;/p&gt;  &lt;p&gt;There are three distinct stages to our automation, each happening in different projects:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;strong&gt;Add-In assembly project:&lt;/strong&gt; Build Version Incremement Add-in updates the Assembly and File versions of the changed assemblies &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Add-In installer project:&lt;/strong&gt; A pre-build target in the WiX project that builds the installer for the changed assemblies which:       &lt;ul&gt;       &lt;li&gt;Updates the installer’s product version and output file name &lt;/li&gt;        &lt;li&gt;Updates its file name and file version entry in AddIn.xml &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;WSSX Package project: &lt;/strong&gt;A pre-build target in the WSSX project checks all file versions in AddIn.xml and compares them to the current package version, then:  &lt;ul&gt;       &lt;li&gt;Replaces the package version with the highest file version, if the highest file version is higher than the current package version &lt;/li&gt;     &lt;/ul&gt;      &lt;p&gt;&lt;em&gt;OR&lt;/em&gt; &lt;/p&gt;      &lt;ul&gt;       &lt;li&gt;Increments the package version by one, if none of the file versions are higher than the current package version &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The end result is that:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Any changed files get a new version number &lt;/li&gt;    &lt;li&gt;Their parent Windows Installer packages get a new version number (both in the Windows Installer package itself and the WSSX package’s metadata) &lt;/li&gt;    &lt;li&gt;The main WSSX package gets a new version number &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;And, just like that, we hit &lt;a href="/archive/2011/05/31/whs-2011-add-in-deployment-package-upgrades.aspx" target="_blank"&gt;all our requirements&lt;/a&gt; for building a WSSX package that supports upgrades.&lt;/p&gt;  &lt;h3&gt;1. Add-In Assembly Project&lt;/h3&gt;  &lt;p&gt;In the &lt;a href="http://www.tentaclesoftware.com/download/WssxPackageExample.zip" target="_blank"&gt;sample project&lt;/a&gt;, we’re deploying a Dashboard Add-In called “WssxPackageExample”. This project is a C# Class Library project that contains our Dashboard tab. It actually works, so you can build the sample project and deploy it to your test server.&lt;/p&gt;  &lt;p&gt;We’re going to use the output of this project to determine the version number of the WiX installer; it’s the core file we’ll be delivering with this WiX installer.&lt;/p&gt;  &lt;h4&gt;Build Version Increment Settings&lt;/h4&gt;  &lt;p&gt;We don’t need to do much here. Essentially, we just want to set up Build Version Increment for this product to increase the version number of the output assembly each time we build the project.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Open the Tools drop-down menu inside Visual Studio &lt;/li&gt;    &lt;li&gt;Choose Build Version Incremement –&amp;gt; Settings &lt;/li&gt;    &lt;li&gt;Select the appropriate project from the list &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a href="http://blog.tentaclesoftware.com/images/blog_tentaclesoftware_com/Windows-Live-Writer/Automating_9BD7/image_8.png" rel="lightbox"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.tentaclesoftware.com/images/blog_tentaclesoftware_com/Windows-Live-Writer/Automating_9BD7/image_thumb_3.png" width="400" height="240" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Now we change the versioning style so that our Build and Revision fields of the version number are incremented for each build, and make sure that both &lt;em&gt;Update AssemblyFileVersion&lt;/em&gt; and &lt;em&gt;Update AssemblyVersion&lt;/em&gt; are set to ‘true’.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog.tentaclesoftware.com/images/blog_tentaclesoftware_com/Windows-Live-Writer/Automating_9BD7/image_4.png" rel="lightbox"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.tentaclesoftware.com/images/blog_tentaclesoftware_com/Windows-Live-Writer/Automating_9BD7/image_thumb_1.png" width="400" height="240" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Now, before every build of this project, the Build and Revision fields of the assembly’s version will be incremented to indicate that this is a new version of the assembly.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Windows Installer only uses the first three fields of a product’s version to determine if an upgrade needs to occur, so we must make sure we’re incrementing at least the Build field each time.&lt;/p&gt;    &lt;p&gt;When you make a major change to the product (a large new feature, for example), it’s a good idea to manually change the Major or Minor field as well. &lt;/p&gt;    &lt;p&gt;For example, if the current version for the assembly is 1.2.23.1006, and you add a brand new shiny feature, you should edit &lt;em&gt;AssemblyInfo.cs&lt;/em&gt; for the project and change the version to 1.3.0.1006. Build Version Increment will change the version to 1.3.1.1007 on the next build.&lt;/p&gt;    &lt;p&gt;I like to increment the Revision field to keep track of how many builds the project has had. I don’t reset this field when manually updating the version for a product.&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If your Add-In also has client components, you’d apply these changes to the core project reference for each client installer as well.&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;2. Add-In Installer Project&lt;/h3&gt;  &lt;p&gt;Our Add-In installer project (WiX, in our case) wraps up our Add-In’s files into a Windows Installer (*.msi) package. &lt;/p&gt;  &lt;p&gt;For each WiX project, I designate a target file that serves as the source for version numbers. In the case of Dashboard Add-Ins, this is usually the assembly that contains the main Dashboard tab and associated code.&lt;/p&gt;  &lt;p&gt;The target file is used to set the Product Version property and output file name for the Windows Installer package. The Product Version, Product Code, and output file name from the Windows Installer package are then pushed to the AddIn.xml file in the WSSX project.&lt;/p&gt;  &lt;p&gt;I’ve talked about &lt;a href="/archive/2010/08/05/99.aspx"&gt;automatic version numbers for WiX projects before&lt;/a&gt;. This method is a modified version of what we use for WHS v1 Add-Ins.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;Note: &lt;/strong&gt;I’m using a static Product Id in my WiX definitions. &lt;/p&gt;    &lt;p&gt;There’s some debate as to whether it’s better to use Major upgrades for every build (by setting Product Id to “*” and allowing WiX to auto-generate a new GUID every build) or to use Minor upgrades unless the there has been a comprehensive change to the product. &lt;/p&gt;    &lt;p&gt;The &lt;a href="http://msdn.microsoft.com/en-us/library/aa370579(VS.85).aspx" target="_blank"&gt;MSDN documentation&lt;/a&gt; seems to encourage the use of Minor upgrades, so that’s what I’m doing below. Also, AddIn.xml requires that you use the exact Product Id/Code for the Windows Installer packages you’re including, so I’ve found it much easier to use a static Id value.&lt;/p&gt;    &lt;p&gt;If you use “*” for Product ID, then you’ll need to figure out another way of getting the Product Code for AddIn.xml.&lt;/p&gt; &lt;/blockquote&gt;  &lt;h4&gt;Product.wxs&lt;/h4&gt;  &lt;p&gt;We need to set the Product Version for the *.wxs file, so that the Windows Installer package is built with the correct version metadata.&lt;/p&gt;  &lt;p&gt;The magic here is in Project References. When you add a Project Reference to a WiX project, you can use some awesome shortcuts when referencing project outputs in your *.wxs file.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Add a new reference to the WiX project &lt;/li&gt;    &lt;li&gt;Change to the Projects tab and select the core assembly for your Add-In &lt;/li&gt;    &lt;li&gt;Click Add, and OK &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;a href="http://blog.tentaclesoftware.com/images/blog_tentaclesoftware_com/Windows-Live-Writer/Automating_9BD7/image_10.png" rel="lightbox"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.tentaclesoftware.com/images/blog_tentaclesoftware_com/Windows-Live-Writer/Automating_9BD7/image_thumb_4.png" width="400" height="405" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Now we can use the &lt;em&gt;TargetFileName&lt;/em&gt; property of our Project Reference to bind its output FileVersion as our Product Version.&lt;/p&gt;  &lt;p&gt;Edit the *.wxs file and change the Product Version:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:eead8be6-7a2f-4831-b913-50b6208b9b56" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;  &amp;lt;Product
    Name='WssxPackageExample'
    Id='{EDBAEE8D-BDD1-48AA-8F35-2B2ABCA43E8A}'
    UpgradeCode='{45C6030C-766A-46A5-A635-6FA167018CE3}'
    Language='1033'
    Codepage='1252'
    Version='!(bind.FileVersion.$(var.WssxPackageExample.TargetFileName))'
    Manufacturer='Tentacle Software Ltd.'&amp;gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, we can use our Project Reference with $(var.&amp;lt;ProjectName&amp;gt;.&amp;lt;Property&amp;gt;). We’re using more WiX-magic with bind.FileVersion that extracts the version from our target assembly and returns it as a text string.&lt;/p&gt;

&lt;p&gt;Each time we build this *.wxs file WiX will extract the version of our target assembly automatically and assign it to the Version of our Windows Installer package&lt;/p&gt;

&lt;h4&gt;*.wixproj&lt;/h4&gt;

&lt;p&gt;Now we need to continue our adventure with MSBuild, by adding a “BeforeBuild” target to our WiX project file that sets the correct output file name and updates AddIn.xml with correct metadata.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Right-click the WiX project node in Solution Explorer and choose “Unload Project” &lt;/li&gt;

  &lt;li&gt;Right-click the project node again and choose “Edit &amp;lt;projectname&amp;gt;.wixproj” &lt;/li&gt;

  &lt;li&gt;You’ll be presented with the *.wixproj file in an XML editor &lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note: In the sample project, we’re editing WssxPackageExample.Server.wixproj.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At the bottom of the project file, before the closing &amp;lt;/Project&amp;gt; node, you’ll see the following comments:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:241361c8-9cca-4928-905a-7b5571222f27" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;  &amp;lt;!--
	To modify your build process, add your task inside one of the targets below and uncomment it.
	Other similar extension points exist, see Wix.targets.
	&amp;lt;Target Name="BeforeBuild"&amp;gt;
	&amp;lt;/Target&amp;gt;
	&amp;lt;Target Name="AfterBuild"&amp;gt;
	&amp;lt;/Target&amp;gt;
	--&amp;gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Sounds like us, right? We’re going to paste a big chunk of XML after that comment, and modify the crap out of your build process. &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Note: &lt;/strong&gt;If you find the following hard to read or copy, download the sample project; you’ll find this XML at the bottom of the WssxPackageExample.Server.wixproj file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:f3c36eaf-2d0a-4554-86b3-c8ac6b3b54c1" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;  &amp;lt;UsingTask 
	TaskName="Microsoft.Build.Tasks.XmlPoke" 
	AssemblyName="Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/&amp;gt;
  &amp;lt;UsingTask 
	TaskName="Microsoft.Build.Tasks.XmlPeek" 
	AssemblyName="Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;TargetProjectName&amp;gt;WssxPackageExample&amp;lt;/TargetProjectName&amp;gt;
    &amp;lt;WsxFileName&amp;gt;Product.wxs&amp;lt;/WsxFileName&amp;gt;
    &amp;lt;AddInXmlProjectName&amp;gt;WssxPackageExample.AddIn&amp;lt;/AddInXmlProjectName&amp;gt;
    &amp;lt;WxsPath&amp;gt;$(ProjectDir)$(WsxFileName)&amp;lt;/WxsPath&amp;gt;
    &amp;lt;AddInXmlPath&amp;gt;$(SolutionDir)$(AddInXmlProjectName)\AddIn.xml&amp;lt;/AddInXmlPath&amp;gt;
    &amp;lt;WxsNamespace&amp;gt;&amp;amp;lt;Namespace Prefix='wxs' Uri='http://schemas.microsoft.com/wix/2006/wi' /&amp;amp;gt;&amp;lt;/WxsNamespace&amp;gt;
    &amp;lt;AddInXmlNamespace&amp;gt;&amp;amp;lt;Namespace Prefix='wss' Uri='http://schemas.microsoft.com/WindowsServerSolutions/2010/03/Addins' /&amp;amp;gt;&amp;lt;/AddInXmlNamespace&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;
  &amp;lt;Target Name="BeforeBuild" DependsOnTargets="SetWixOutputFilename;UpdateAddInXmlFileNode" /&amp;gt;
  &amp;lt;Target Name="SetWixOutputFilename"&amp;gt;
    &amp;lt;!-- Get ProjectReference output assembly versions for project 'WssDeploymentTest' --&amp;gt;
    &amp;lt;AssignProjectConfiguration ProjectReferences="@(ProjectReference)" Condition="'%(Name)' == '$(TargetProjectName)'" SolutionConfigurationContents="$(CurrentSolutionConfigurationContents)"&amp;gt;
      &amp;lt;Output TaskParameter="AssignedProjects" ItemName="ProjectReferenceWithBuildConfig" /&amp;gt;
    &amp;lt;/AssignProjectConfiguration&amp;gt;
    &amp;lt;Message Text="Found project reference %(ProjectReferenceWithBuildConfig.Name) with config %(ProjectReferenceWithBuildConfig.FullConfiguration)" Condition="'@(ProjectReferenceWithBuildConfig)' != ''" /&amp;gt;
    &amp;lt;MSBuild Projects="@(ProjectReferenceWithBuildConfig)" UseResultsCache="true" Targets="Build" Properties="%(ProjectReferenceWithBuildConfig.SetConfiguration);%(ProjectReferenceWithBuildConfig.SetPlatform)" ContinueOnError="false"&amp;gt;
      &amp;lt;Output TaskParameter="TargetOutputs" ItemName="ProjectReferenceOutputs" /&amp;gt;
    &amp;lt;/MSBuild&amp;gt;
    &amp;lt;Message Text="Project Outputs: @(ProjectReferenceOutputs)" /&amp;gt;
    &amp;lt;!-- Get AssemblyVersions for ProjectReference output assembly --&amp;gt;
    &amp;lt;GetAssemblyIdentity AssemblyFiles="@(ProjectReferenceOutputs)"&amp;gt;
      &amp;lt;Output TaskParameter="Assemblies" ItemName="AssemblyVersions" /&amp;gt;
    &amp;lt;/GetAssemblyIdentity&amp;gt;
    &amp;lt;CreateProperty Value="%(AssemblyVersions.Version)"&amp;gt;
      &amp;lt;Output TaskParameter="Value" PropertyName="TargetAssemblyVersion" /&amp;gt;
    &amp;lt;/CreateProperty&amp;gt;
    &amp;lt;Message Text="Target Assembly Version: $(TargetAssemblyVersion)" /&amp;gt;
    &amp;lt;!-- Set WiX TargetName based on OutputName and AssemblyVersions --&amp;gt;
    &amp;lt;CreateProperty Value="$(OutputName).$(TargetAssemblyVersion)"&amp;gt;
      &amp;lt;Output TaskParameter="Value" PropertyName="TargetName" /&amp;gt;
    &amp;lt;/CreateProperty&amp;gt;
    &amp;lt;CreateProperty Value="$(TargetName)$(TargetExt)"&amp;gt;
      &amp;lt;Output TaskParameter="Value" PropertyName="TargetFileName" /&amp;gt;
    &amp;lt;/CreateProperty&amp;gt;
    &amp;lt;CreateProperty Value="$(TargetDir)$(TargetFileName)"&amp;gt;
      &amp;lt;Output TaskParameter="Value" PropertyName="TargetPath" /&amp;gt;
    &amp;lt;/CreateProperty&amp;gt;
    &amp;lt;Message Text="Target File Name: $(TargetFileName)" /&amp;gt;
  &amp;lt;/Target&amp;gt;
  &amp;lt;Target Name="UpdateAddInXmlFileNode"&amp;gt;
    &amp;lt;!-- Get ProductCode from .wxs file --&amp;gt;
    &amp;lt;XmlPeek XmlInputPath="$(WxsPath)" Query="//wxs:Wix/wxs:Product/@Id" Namespaces="$(WxsNamespace)"&amp;gt;
      &amp;lt;Output TaskParameter="Result" ItemName="ProductCode" /&amp;gt;
    &amp;lt;/XmlPeek&amp;gt;
    &amp;lt;Message Text="Product Code: @(ProductCode)"/&amp;gt;
    &amp;lt;!-- Update AddIn.xml file to use correct Name, Version and ProductCode --&amp;gt;
    &amp;lt;XmlPoke XmlInputPath="$(AddInXmlPath)" Query="//wss:Package/wss:ServerBinary/wss:File/wss:Name" Namespaces="$(AddInXmlNamespace)" Value="$(TargetFileName)" /&amp;gt;
    &amp;lt;XmlPoke XmlInputPath="$(AddInXmlPath)" Query="//wss:Package/wss:ServerBinary/wss:File/wss:Version" Namespaces="$(AddInXmlNamespace)" Value="$(TargetAssemblyVersion)" /&amp;gt;
    &amp;lt;XmlPoke XmlInputPath="$(AddInXmlPath)" Query="//wss:Package/wss:ServerBinary/wss:File/wss:ProductCode" Namespaces="$(AddInXmlNamespace)" Value="@(ProductCode)" /&amp;gt;
  &amp;lt;/Target&amp;gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The comments in the XML above should give you a hint about what’s going on here:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Find our target project’s output &lt;/li&gt;

  &lt;li&gt;Grab its AssemblyVersion &lt;/li&gt;

  &lt;li&gt;Set our output file name to &amp;lt;Output&amp;gt;.&amp;lt;Version&amp;gt;.msi &lt;/li&gt;

  &lt;li&gt;Get the Product ID value from our *.wxs file &lt;/li&gt;

  &lt;li&gt;Update AddIn.xml with the Product ID, version, and output file name &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key bits you’ll need to customize to get this to work in your projects are in the PropertyGroup at the top of our XML block:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:84fa67da-096d-4e39-8ebd-c351992882f4" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;TargetProjectName&amp;gt;WssxPackageExample&amp;lt;/TargetProjectName&amp;gt;
    &amp;lt;WsxFileName&amp;gt;Product.wxs&amp;lt;/WsxFileName&amp;gt;
    &amp;lt;AddInXmlProjectName&amp;gt;WssxPackageExample.AddIn&amp;lt;/AddInXmlProjectName&amp;gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because you’ll probably have multiple Project References when you build a real Add-In installer, we need to know which project is the target that we’ll use for version numbering. We also need to know the name of the *.wxs file we’re compiling and the name of the WSSX project that contains our AddIn.xml file.&lt;/p&gt;

&lt;p&gt;The other bit we need to look at is the File node we’re editing in AddIn.xml. In this case, we’re adding this BeforeBuild target to the *.wixproj that builds the ServerBinary for our Add-In, so we’re setting metadata in AddIn.xml for the ServerBinary node. &lt;/p&gt;

&lt;p&gt;Your ClientBinary32 and ClientBinary64 WiX projects will need to edit the following tasks to use the correct xpath query:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:0454ac56-d8f8-45e4-bdb8-f61fa9772e55" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;    &amp;lt;XmlPoke XmlInputPath="$(AddInXmlPath)" Query="//wss:Package/wss:ServerBinary/wss:File/wss:Name" Namespaces="$(AddInXmlNamespace)" Value="$(TargetFileName)" /&amp;gt;
    &amp;lt;XmlPoke XmlInputPath="$(AddInXmlPath)" Query="//wss:Package/wss:ServerBinary/wss:File/wss:Version" Namespaces="$(AddInXmlNamespace)" Value="$(TargetAssemblyVersion)" /&amp;gt;
    &amp;lt;XmlPoke XmlInputPath="$(AddInXmlPath)" Query="//wss:Package/wss:ServerBinary/wss:File/wss:ProductCode" Namespaces="$(AddInXmlNamespace)" Value="@(ProductCode)" /&amp;gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Change &lt;em&gt;ServerBinary&lt;/em&gt; to &lt;em&gt;ClientBinary32&lt;/em&gt; or &lt;em&gt;ClientBinary64&lt;/em&gt; in the Query string above. Check out the BeforeBuild targets in WssxPackageExample.Client32 and WssxPackageExample.Client64 in the sample project for concrete examples.&lt;/p&gt;

&lt;p&gt;Now every time we build this WiX project we’ll set the output Windows Installer package filename to include the version number of the package (which is also the version number of the target assembly we’re delivering). Then we’ll update the appropriate File node in AddIn.xml with the correct ProductCode, Version, and file Name.&lt;/p&gt;

&lt;h3&gt;3. WSSX Package Project&lt;/h3&gt;

&lt;p&gt;Now that we’ve set and updated version numbers for our assemblies and Windows Installer packages, and set correct metadata in AddIn.xml, we need to make sure that we’re also updating the version for the WSSX package itself.&lt;/p&gt;

&lt;h4&gt;*.wssxproj&lt;/h4&gt;

&lt;p&gt;Edit your *.wssxproj file, and you’ll find a similar “To modify your build process…” comment as you did in the WiX project file. &lt;/p&gt;

&lt;p&gt;We’re going to paste another big chunk of XML right after that comment.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Note: &lt;/strong&gt;If you find the following hard to read or copy, download the sample project; you’ll find this XML at the bottom of the WssxPackageExample.AddIn.wssxproj file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:a1775e9b-c808-46c6-93e5-ec8cece0b077" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;  &amp;lt;UsingTask 
TaskName="Microsoft.Build.Tasks.XmlPoke" 
AssemblyName="Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/&amp;gt;
  &amp;lt;UsingTask 
TaskName="Microsoft.Build.Tasks.XmlPeek" 
AssemblyName="Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/&amp;gt;
  &amp;lt;UsingTask 
TaskName="GetHighestVersionNumber" 
TaskFactory="CodeTaskFactory" 
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"&amp;gt;
    &amp;lt;ParameterGroup&amp;gt;
      &amp;lt;VersionList Required="True" ParameterType="System.String[]"/&amp;gt;
      &amp;lt;Result ParameterType="System.String" Output="True"/&amp;gt;
    &amp;lt;/ParameterGroup&amp;gt;
    &amp;lt;Task&amp;gt;
      &amp;lt;Reference Include="mscorlib" /&amp;gt;
      &amp;lt;Using Namespace="System" /&amp;gt;
      &amp;lt;Using Namespace="System.Linq" /&amp;gt;
      &amp;lt;Code Type="Fragment" Language="cs"&amp;gt;
        &amp;lt;![CDATA[
          Result = VersionList.Select(v =&amp;gt; Version.Parse(v)).OrderByDescending(v =&amp;gt; v).FirstOrDefault().ToString();
        ]]&amp;gt;
      &amp;lt;/Code&amp;gt;
    &amp;lt;/Task&amp;gt;
  &amp;lt;/UsingTask&amp;gt;
  &amp;lt;UsingTask 
TaskName="IncrementVersionNumber" 
TaskFactory="CodeTaskFactory" 
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"&amp;gt;
    &amp;lt;ParameterGroup&amp;gt;
      &amp;lt;VersionString Required="True" ParameterType="System.String"/&amp;gt;
      &amp;lt;Result ParameterType="System.String" Output="True"/&amp;gt;
    &amp;lt;/ParameterGroup&amp;gt;
    &amp;lt;Task&amp;gt;
      &amp;lt;Reference Include="mscorlib" /&amp;gt;
      &amp;lt;Using Namespace="System" /&amp;gt;
      &amp;lt;Using Namespace="System.Linq" /&amp;gt;
      &amp;lt;Code Type="Fragment" Language="cs"&amp;gt;
        &amp;lt;![CDATA[
            Version current = Version.Parse(VersionString);
            Result = new Version(current.Major, current.Minor, current.Build + 1, current.Revision).ToString();
        ]]&amp;gt;
      &amp;lt;/Code&amp;gt;
    &amp;lt;/Task&amp;gt;
  &amp;lt;/UsingTask&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;AddInXmlPath&amp;gt;$(ProjectDir)AddIn.xml&amp;lt;/AddInXmlPath&amp;gt;
    &amp;lt;WxsNamespace&amp;gt;&amp;amp;lt;Namespace Prefix='wxs' Uri='http://schemas.microsoft.com/wix/2006/wi' /&amp;amp;gt;&amp;lt;/WxsNamespace&amp;gt;
    &amp;lt;AddInXmlNamespace&amp;gt;&amp;amp;lt;Namespace Prefix='wss' Uri='http://schemas.microsoft.com/WindowsServerSolutions/2010/03/Addins' /&amp;amp;gt;&amp;lt;/AddInXmlNamespace&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;
  &amp;lt;Target Name="BeforePack" DependsOnTargets="GetPackageVersions;ReplaceAddInXmlPackageVersion;IncrementAddInXmlPackageVersion" /&amp;gt;
  &amp;lt;Target Name="GetPackageVersions"&amp;gt;
    &amp;lt;!-- Get current Package Version from AddIn.Xml --&amp;gt;
    &amp;lt;XmlPeek XmlInputPath="$(AddInXmlPath)" Query="//wss:Package/wss:Version/text()" Namespaces="$(AddInXmlNamespace)"&amp;gt;
      &amp;lt;Output TaskParameter="Result" PropertyName="PackageVersion" /&amp;gt;
    &amp;lt;/XmlPeek&amp;gt;
    &amp;lt;Message Text="Package Version: $(PackageVersion)"/&amp;gt;
    &amp;lt;!-- Get current ServerBinary version from AddIn.xml --&amp;gt;
    &amp;lt;XmlPeek XmlInputPath="$(AddInXmlPath)" Query="//wss:Package/wss:ServerBinary/wss:File/wss:Version/text()" Namespaces="$(AddInXmlNamespace)"&amp;gt;
      &amp;lt;Output TaskParameter="Result" ItemName="FileVersion" /&amp;gt;
    &amp;lt;/XmlPeek&amp;gt;
    &amp;lt;!-- Get current ClientBinary32 version from AddIn.xml --&amp;gt;
    &amp;lt;XmlPeek XmlInputPath="$(AddInXmlPath)" Query="//wss:Package/wss:ClientBinary32/wss:File/wss:Version/text()" Namespaces="$(AddInXmlNamespace)"&amp;gt;
      &amp;lt;Output TaskParameter="Result" ItemName="FileVersion" /&amp;gt;
    &amp;lt;/XmlPeek&amp;gt;
    &amp;lt;!-- Get current ClientBinary64 version from AddIn.xml --&amp;gt;
    &amp;lt;XmlPeek XmlInputPath="$(AddInXmlPath)" Query="//wss:Package/wss:ClientBinary64/wss:File/wss:Version/text()" Namespaces="$(AddInXmlNamespace)"&amp;gt;
      &amp;lt;Output TaskParameter="Result" ItemName="FileVersion" /&amp;gt;
    &amp;lt;/XmlPeek&amp;gt;
    &amp;lt;!-- Get the current highest file version --&amp;gt;
    &amp;lt;GetHighestVersionNumber VersionList="@(FileVersion)"&amp;gt;
      &amp;lt;Output PropertyName="HighestFileVersion" TaskParameter="Result" /&amp;gt;
    &amp;lt;/GetHighestVersionNumber&amp;gt;
    &amp;lt;Message Text="Highest File Version: $(HighestFileVersion)" /&amp;gt;
    &amp;lt;!-- Compare Package version with our version (we Version.Parse() to perform the correct comparison) --&amp;gt;
    &amp;lt;CreateProperty Value="$([System.Version]::Parse($(HighestFileVersion)).CompareTo($([System.Version]::Parse($(PackageVersion)))))"&amp;gt;
      &amp;lt;Output TaskParameter="Value" PropertyName="VersionCompareResult" /&amp;gt;
    &amp;lt;/CreateProperty&amp;gt;
  &amp;lt;/Target&amp;gt;
  &amp;lt;Target Name="ReplaceAddInXmlPackageVersion" Condition="$(VersionCompareResult) == 1"&amp;gt;
    &amp;lt;!-- Replace Package Version if highest file version is greater than --&amp;gt;
    &amp;lt;XmlPoke XmlInputPath="$(AddInXmlPath)" Query="//wss:Package/wss:Version" Namespaces="$(AddInXmlNamespace)" Value="$(HighestFileVersion)" /&amp;gt;
    &amp;lt;Message Text="Package Version Updated: $(HighestFileVersion)" /&amp;gt;
  &amp;lt;/Target&amp;gt;
  &amp;lt;Target Name="IncrementAddInXmlPackageVersion" Condition="$(VersionCompareResult) &amp;amp;lt;= 0"&amp;gt;
    &amp;lt;!-- Increment current Package Version if highest file version is less than or equal --&amp;gt;
    &amp;lt;IncrementVersionNumber VersionString="$(PackageVersion)"&amp;gt;
      &amp;lt;Output PropertyName="IncrementedVersion" TaskParameter="Result" /&amp;gt;
    &amp;lt;/IncrementVersionNumber&amp;gt;
    &amp;lt;XmlPoke XmlInputPath="$(AddInXmlPath)" Query="//wss:Package/wss:Version" Namespaces="$(AddInXmlNamespace)" Value="$(IncrementedVersion)" /&amp;gt;
    &amp;lt;Message Text="Package Version Updated: $(IncrementedVersion)" /&amp;gt;
  &amp;lt;/Target&amp;gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The comments should let you know what we’re doing:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Find our current Package Version &lt;/li&gt;

  &lt;li&gt;Get the versions of all our Binaries (the Windows Installer packages we’re including in the final *.wssx file) &lt;/li&gt;

  &lt;li&gt;Compare the Package Version with the highest Version from our Binaries &lt;/li&gt;

  &lt;li&gt;If our highest Binary Version is higher than the current Package Version, we replace the Package Version &lt;/li&gt;

  &lt;li&gt;If our Package Version is the same as, or higher than, the highest Binary Version, we increment the Package Version by one &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No need to do any customization here, it’s all based on the previous steps that have injected the right values into our AddIn.xml file.&lt;/p&gt;

&lt;p&gt;The whole point of this chunk of MSBuild voodoo is to make sure our *.wssx package always has a higher Package Version for each build than when it started.&lt;/p&gt;

&lt;h3&gt;Look Ma, No Hands!&lt;/h3&gt;

&lt;p&gt;And that’s it, for now.&lt;/p&gt;

&lt;p&gt;When you make a change to one of the assemblies that makes up your Add-In, those changes will ensure that your final *.wssx file is built with a new version number, and as a bonus your Add-In will support in-place upgrades. All without manual edits to any files in the process.&lt;/p&gt;

&lt;p&gt;Removing manual steps from any build process is a win for me; any time I can reduce cognitive load, and therefore reduce the chance for screw-ups, I’m a happy camper.&lt;/p&gt;

&lt;p&gt;If you have any questions (or if you’ve actually read to the end of this post!) please drop something into the comments below, or fire us an email using the &lt;a href="http://www.tentaclesoftware.com/contact/"&gt;Contact&lt;/a&gt; page.&lt;/p&gt;

&lt;p&gt;So what’s next? Well, we still need to talk about signing our *.wssx files, because the signature is actually checked during install now! And we want to avoid that nasty “publisher could not be verified” message, right?&lt;/p&gt;&lt;img src="http://blog.tentaclesoftware.com/aggbug/118.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Sam Wood</dc:creator>
            <guid>http://blog.tentaclesoftware.com/archive/2011/07/01/automating-windows-server-solutions-add-in-package-wssx-builds-to.aspx</guid>
            <pubDate>Fri, 01 Jul 2011 04:26:51 GMT</pubDate>
            <comments>http://blog.tentaclesoftware.com/archive/2011/07/01/automating-windows-server-solutions-add-in-package-wssx-builds-to.aspx#feedback</comments>
            <slash:comments>2</slash:comments>
            <wfw:commentRss>http://blog.tentaclesoftware.com/comments/commentRss/118.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Windows Server Solutions Add-In Package Project (*.wssx) for Visual Studio 2010</title>
            <category>Development</category>
            <category>WSSX</category>
            <category>Windows Home Server</category>
            <link>http://blog.tentaclesoftware.com/archive/2011/06/24/windows-server-solutions-add-in-package-project-wssx-for-visual.aspx</link>
            <description>&lt;p&gt;A few weeks ago I &lt;a href="/archive/2011/05/31/whs-2011-add-in-deployment-package-upgrades.aspx"&gt;posted recommendations for structuring your WSSX cabinet files&lt;/a&gt; and installer packages. I also promised to post some magic automation techniques to make building *.wssx files much, much easier.&lt;/p&gt;  &lt;p&gt;The magic part is coming in the next post, because we still need to cover some foundations properly!&lt;/p&gt;  &lt;p&gt;To that end, I’ve put together a custom Visual Studio 2010 project type that allows you to manage your *.wssx build process in the same way you manage every other project in your solution.&lt;/p&gt;  &lt;p&gt;It’s now &lt;a href="http://visualstudiogallery.msdn.microsoft.com/55bd7010-ca1f-4995-8374-82fec48f1d13" target="_blank"&gt;up on the Visual Studio Gallery for download&lt;/a&gt; as an extension. Here’s the blurb:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Adds support to Visual Studio 2010 for *.wssx cabinet files required to distribute &lt;a href="http://msdn.microsoft.com/en-us/library/gg513877.aspx" target="_blank"&gt;Windows Server Solutions SDK&lt;/a&gt; Add-Ins for Windows Home Server 2011, Windows Small Business Server 2011 Essentials, and Windows Storage Server 2008 R2 Essentials.&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;Complete Visual Studio 2010 project type that fully automates creating *.wssx files &lt;/li&gt;      &lt;li&gt;Full makecab automation &lt;/li&gt;      &lt;li&gt;Full MSBuild support and integration points &lt;/li&gt;      &lt;li&gt;Automatic packaging of project reference outputs and content items &lt;/li&gt;      &lt;li&gt;Post-package signing support &lt;/li&gt;      &lt;li&gt;Includes templates for required Add-In metadata files &lt;/li&gt;   &lt;/ul&gt;    &lt;p&gt;&lt;strong&gt;Getting Started&lt;/strong&gt;&lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;Add a new WSSX project (File –&amp;gt; New Project –&amp;gt; WSSX –&amp;gt; WSSX Add-In Package) &lt;/li&gt;      &lt;li&gt;Add your server and client installer projects to your WSSX project as References &lt;/li&gt;      &lt;li&gt;Edit AddIn.xml to point to the correct installer file names and ProductCodes &lt;/li&gt;      &lt;li&gt;Build! &lt;/li&gt;   &lt;/ol&gt;    &lt;p&gt;&lt;strong&gt;Learn More&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;Learn more about this project type and automating Windows Server Solutions Add-In builds at the &lt;a href="http://www.tentaclesoftware.com/wssx" target="_blank"&gt;Tentacle Software Blog&lt;/a&gt;.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Basically, you don’t have to mess around with building your own DDF files or running MAKECAB as part of your post-build process; we handle all that for you. Add the files and project outputs to the WSSX project that you want to be included in the cabinet and we take care of the rest.&lt;/p&gt;  &lt;p&gt;I’ve also created &lt;a href="http://blog.tentaclesoftware.com/category/9.aspx"&gt;a new WSSX category&lt;/a&gt; for the blog that will contain our recommendations for using the new project type, automation tips, and general tutorials.&lt;/p&gt;  &lt;p&gt;The automation techniques I’ll talk about soon will be based on this project type, so go download it and have a play in the meantime. Feedback is always welcome!&lt;/p&gt;&lt;img src="http://blog.tentaclesoftware.com/aggbug/117.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Sam Wood</dc:creator>
            <guid>http://blog.tentaclesoftware.com/archive/2011/06/24/windows-server-solutions-add-in-package-project-wssx-for-visual.aspx</guid>
            <pubDate>Fri, 24 Jun 2011 04:41:36 GMT</pubDate>
            <comments>http://blog.tentaclesoftware.com/archive/2011/06/24/windows-server-solutions-add-in-package-project-wssx-for-visual.aspx#feedback</comments>
            <wfw:commentRss>http://blog.tentaclesoftware.com/comments/commentRss/117.aspx</wfw:commentRss>
        </item>
        <item>
            <title>WHS 2011 Add-In Deployment Package Upgrades</title>
            <category>Development</category>
            <category>Windows Home Server</category>
            <category>WSSX</category>
            <link>http://blog.tentaclesoftware.com/archive/2011/05/31/whs-2011-add-in-deployment-package-upgrades.aspx</link>
            <description>&lt;p&gt;The Windows Home Server v1 extensibility framework missed out an important component; Microsoft implemented no upgrade capability for already-installed Add-Ins. &lt;/p&gt;  &lt;p&gt;The “upgrade” process required that the user uninstall the old version of your Add-In, and then install the new version. If your installer wasn’t checking for existing versions of your Add-In users could easily find themselves with multiple instances your Add-In installed, with no way to remove them without manual registry editing.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Windows_Home_Server_2011" target="_blank"&gt;Windows Home Server 2011&lt;/a&gt; (and the other platforms that support the &lt;a href="http://msdn.microsoft.com/en-us/library/gg513877.aspx" target="_blank"&gt;Windows Server Solutions SDK&lt;/a&gt;) now support Add-In upgrades properly. A user can now download a new version of your Add-In, install it from a client machine, and WHS and MSI will handle the upgrade process cleanly. Your users can even upgrade while the Dashboard is running (they’ll need to restart the Dashboard to see changes to any files that were in-use, of course).&lt;/p&gt;  &lt;p&gt;As a developer you’ll need to do a bit of work to make this happen, but the result is well worth the effort.&lt;/p&gt;  &lt;p&gt;I’m going to assume some prior knowledge here. You should know how to &lt;a href="http://blog.tentaclesoftware.com/search.aspx?q=wix" target="_blank"&gt;navigate around a WiX file&lt;/a&gt;, and the general concepts for &lt;a href="http://msdn.microsoft.com/en-us/library/gg513966.aspx" target="_blank"&gt;packaging WSS Add-Ins&lt;/a&gt;. Also, as with any WiX article, &lt;em&gt;do not&lt;/em&gt; use the GUIDs in the following code samples; GUIDs must be unique, and if you copy mine they won’t be!&lt;/p&gt;  &lt;h4&gt;Add-In Deployment Package Setup&lt;/h4&gt;  &lt;p&gt;The upgrade process works by comparing the version number of your Add-In. Well, it works by comparing a whole bunch of version numbers, in a bunch of different places. WHS 2011 and Microsoft Installer check these version numbers to see if any upgrades need to be performed when your Add-In is (re)installed.&lt;/p&gt;  &lt;p&gt;It pays to set these version numbers up correctly when you’re first creating your deployment package so you’re ready to go for upgrades later.&lt;/p&gt;  &lt;p&gt;These are the relevant sections of the &lt;em&gt;AddIn.xml&lt;/em&gt;, &lt;em&gt;&amp;lt;product&amp;gt;.wxs&lt;/em&gt;, and &lt;em&gt;AssemblyInfo.cs&lt;/em&gt; files that make up a WSS Add-In package.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;AddIn.xml&lt;/strong&gt;&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:a3b66709-477c-4d4d-a222-e81116833e42" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;Package 
  xmlns="http://schemas.microsoft.com/WindowsServerSolutions/2010/03/Addins" 
  xmlns:i="http://www.w3.org/2001/XMLSchema-instance"&amp;gt;
  &amp;lt;Id&amp;gt;{6DA3406C-6527-4AA9-BAB3-6E1F508B39FA}&amp;lt;/Id&amp;gt;
  &amp;lt;Version&amp;gt;1.0.0.0&amp;lt;/Version&amp;gt;
  &amp;lt;Name&amp;gt;WssDeploymentTest&amp;lt;/Name&amp;gt;
  &amp;lt;Allow32BitOn64BitClients&amp;gt;false&amp;lt;/Allow32BitOn64BitClients&amp;gt;
  &amp;lt;ServerBinary&amp;gt;
    &amp;lt;File&amp;gt;
      &amp;lt;ProductCode&amp;gt;{59BD72A5-5DAB-4E6D-9B0A-980CB2A0D0BA}&amp;lt;/ProductCode&amp;gt;
      &amp;lt;Version&amp;gt;1.0&amp;lt;/Version&amp;gt;
      &amp;lt;Name&amp;gt;WssDeploymentTest.Deployment.msi&amp;lt;/Name&amp;gt;
      &amp;lt;Filter&amp;gt;
        &amp;lt;Language&amp;gt;en-US&amp;lt;/Language&amp;gt;
        &amp;lt;IsLanguageFallback&amp;gt;true&amp;lt;/IsLanguageFallback&amp;gt;
      &amp;lt;/Filter&amp;gt;
    &amp;lt;/File&amp;gt;
  &amp;lt;/ServerBinary&amp;gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;AddIn.xml&lt;/em&gt; file is parsed before running any MSI packages. WHS 2011 checks the Package ID, Package Version, and the Version of the ServerBinary File element. &lt;/p&gt;

&lt;p&gt;The ProductCode must match the Product ID value defined in your &lt;em&gt;&amp;lt;product&amp;gt;.wxs&lt;/em&gt; file; WHS 2011 queries Windows Installer for this value when installing and uninstalling your Add-In.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&amp;lt;product&amp;gt;.wxs&lt;/strong&gt;&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:b6da8673-c429-4f3e-bff4-1fbcd3abd9c7" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version='1.0' encoding='Windows-1252'?&amp;gt;
&amp;lt;Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'&amp;gt;
  &amp;lt;Product
    Name='WssDeploymentTest'
    Id='{59BD72A5-5DAB-4E6D-9B0A-980CB2A0D0BA}'
    UpgradeCode='{38736351-4BFC-4B95-9A89-3FED2CBFAB19}'
    Language='1033'
    Codepage='1252'
    Version='1.0.0'
    Manufacturer='Tentacle Software Ltd.'&amp;gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Your WXS file is parsed by WiX and built into an MSI package (in this case, WssDeploymentTest.Deployment.msi). Note the “Version” number here. Also, remember that the Product ID value here &lt;em&gt;must&lt;/em&gt; match the ProductCode in AddIn.xml.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AssemblyInfo.cs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This file represents the properties for the assembly you’re installing. You can manually edit the file, or use the Project Properties Assembly Information GUI wrapper.&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.tentaclesoftware.com/images/blog_tentaclesoftware_com/Windows-Live-Writer/Upgrading-Add-Ins_EF85/image_11.png" width="407" height="405" /&gt;&lt;/p&gt;

&lt;p&gt;If Windows Installer finds that one of the files you’re trying to install already exists, it will compare the version numbers of the two files.&lt;/p&gt;

&lt;h4&gt;Add-In Upgrade Process&lt;/h4&gt;

&lt;p&gt;We’ll assume you’ve got v1.0 of your Add-In installed already. You’ve built another version of your Add-In to fix some bugs and add a new feature, but what happens when you run the new deployment package?&lt;/p&gt;

&lt;p&gt;WHS 2011 and Windows Installer go through a number of checks and gate the upgrade process depending on the version numbers they find at each step. At a high level, the process looks like this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;WHS 2011 checks the Package ID in &lt;em&gt;AddIn.xml&lt;/em&gt;. If we already have that ID installed we then compare the Package Version: 

    &lt;ol&gt;
      &lt;li&gt;If the version of our new Package is greater than what’s installed, &lt;em&gt;&lt;strong&gt;we continue to Step 2.&lt;/strong&gt;&lt;/em&gt; &lt;/li&gt;

      &lt;li&gt;Or, the install stops with a message informing the user that our current version is newer or the same as the version we’re trying to install. &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;

  &lt;li&gt;If our Package Version is newer, WHS 2011 compares the ServerBinary File Version number in &lt;em&gt;AddIn.xml&lt;/em&gt; with the currently installed version: 

    &lt;ol&gt;
      &lt;li&gt;If the version for ServerBinary File in &lt;em&gt;AddIn.xml&lt;/em&gt; is greater than what’s installed, &lt;em&gt;&lt;strong&gt;we continue to step 3.&lt;/strong&gt;&lt;/em&gt; &lt;/li&gt;

      &lt;li&gt;Or, no upgrade of the ServerBinary is performed and we skip the MSI entirely. &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;

  &lt;li&gt;If our ServerBinary File Version is newer, WHS 2011 executes the MSI package. If Microsoft Installer detects that you’re overwriting an existing file, the file versions are compared: 
    &lt;ol&gt;
      &lt;li&gt;If the version of our new file is greater than the existing file, &lt;em&gt;&lt;strong&gt;we attempt to overwrite the existing file&lt;/strong&gt;&lt;/em&gt;. &lt;/li&gt;

      &lt;li&gt;Or, no upgrade of the existing file is performed. &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;“You must restart the server”&lt;/h4&gt;

&lt;p&gt;If you’re attempting to upgrade a file that’s currently locked, the WHS 2011 Add-In install wizard will prompt the user to restart the server. Most of the time (unless you’re doing something crazy), the files will only be locked by the Dashboard itself, so restarting the Dashboard allows the files to be overwritten successfully. &lt;/p&gt;

&lt;p&gt;Because the “must restart” message will persist through subsequent Add-In installs, it’s a good idea to encourage the user to either close the Dashboard before installing a new version of your Add-In or reboot the server as prompted.&lt;/p&gt;

&lt;h4&gt;Changing your Deployment Package to Support Upgrades&lt;/h4&gt;

&lt;p&gt;So, what do you need to do in order for your new deployment package to successfully upgrade existing installations of your Add-In? What values must be changed to make sure your new files overwrite old versions?&lt;/p&gt;

&lt;p&gt;Here’s the cheat sheet:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Increment the Package Version in &lt;em&gt;AddIn.xml&lt;/em&gt; &lt;/li&gt;

  &lt;li&gt;Increment the ServerBinary File Version in &lt;em&gt;AddIn.xml&lt;/em&gt; &lt;/li&gt;

  &lt;li&gt;Increment the Product Version in &lt;em&gt;&amp;lt;product&amp;gt;.wxs&lt;/em&gt; (optional, but recommended for sanity) &lt;/li&gt;

  &lt;li&gt;Increment the Assembly File Version and Assembly Version in &lt;em&gt;AssemblyInfo.cs&lt;/em&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you’re releasing version 1.1 of your Add-In, you’d want something similar to the following (see the changed “Version” numbers in each sample).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AddIn.xml&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Note the changed “Version” elements at lines 6 and 12.&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:ff90ef9b-622b-42f8-8b29-cd3e521ffd09" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;
&amp;lt;Package 
  xmlns="http://schemas.microsoft.com/WindowsServerSolutions/2010/03/Addins" 
  xmlns:i="http://www.w3.org/2001/XMLSchema-instance"&amp;gt;
  &amp;lt;Id&amp;gt;{6DA3406C-6527-4AA9-BAB3-6E1F508B39FA}&amp;lt;/Id&amp;gt;
  &amp;lt;Version&amp;gt;1.1.0.0&amp;lt;/Version&amp;gt;
  &amp;lt;Name&amp;gt;WssDeploymentTest&amp;lt;/Name&amp;gt;
  &amp;lt;Allow32BitOn64BitClients&amp;gt;false&amp;lt;/Allow32BitOn64BitClients&amp;gt;
  &amp;lt;ServerBinary&amp;gt;
    &amp;lt;File&amp;gt;
      &amp;lt;ProductCode&amp;gt;{59BD72A5-5DAB-4E6D-9B0A-980CB2A0D0BA}&amp;lt;/ProductCode&amp;gt;
      &amp;lt;Version&amp;gt;1.1&amp;lt;/Version&amp;gt;
      &amp;lt;Name&amp;gt;WssDeploymentTest.Deployment.msi&amp;lt;/Name&amp;gt;
      &amp;lt;Filter&amp;gt;
        &amp;lt;Language&amp;gt;en-US&amp;lt;/Language&amp;gt;
        &amp;lt;IsLanguageFallback&amp;gt;true&amp;lt;/IsLanguageFallback&amp;gt;
      &amp;lt;/Filter&amp;gt;
    &amp;lt;/File&amp;gt;
  &amp;lt;/ServerBinary&amp;gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;&amp;lt;product&amp;gt;.wxs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Note the changed “Version” elements at line 9.&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:0b28929e-1369-42ec-a929-ddda223a9533" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version='1.0' encoding='Windows-1252'?&amp;gt;
&amp;lt;Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'&amp;gt;
  &amp;lt;Product
    Name='WssDeploymentTest'
    Id='{59BD72A5-5DAB-4E6D-9B0A-980CB2A0D0BA}'
    UpgradeCode='{38736351-4BFC-4B95-9A89-3FED2CBFAB19}'
    Language='1033'
    Codepage='1252'
    Version='1.1.0'
    Manufacturer='Tentacle Software Ltd.'&amp;gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;AssemblyInfo.cs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Note the changed “Version” elements below.&lt;/p&gt;

&lt;p&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px" title="image" border="0" alt="image" src="http://blog.tentaclesoftware.com/images/blog_tentaclesoftware_com/Windows-Live-Writer/Upgrading-Add-Ins_EF85/image_8.png" width="407" height="405" /&gt;&lt;/p&gt;

&lt;h4&gt;Next Steps&lt;/h4&gt;

&lt;p&gt;This whole process is very manual, especially if you’re releasing a lot of builds, and if you miss one version number your upgrade isn’t going to work.&lt;/p&gt;

&lt;p&gt;The solution is, as always, to automate the crap out of things. For File and Assembly Versions, I’m a big fan of the &lt;a href="http://autobuildversion.codeplex.com/" target="_blank"&gt;Build Version Increment Add-In&lt;/a&gt; for Visual Studio. I’ve also posted previously about &lt;a href="http://blog.tentaclesoftware.com/archive/2010/08/05/99.aspx" target="_blank"&gt;automating version numbers in WiX projects&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;I’ll write about my solution for changing values in a random XML file post-build (&lt;em&gt;AddIn.xml&lt;/em&gt; in this case), and how to tie all the wonderful automation together, in a later post. In the mean time, go test your new upgradable Add-In!&lt;/p&gt;&lt;img src="http://blog.tentaclesoftware.com/aggbug/116.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Sam Wood</dc:creator>
            <guid>http://blog.tentaclesoftware.com/archive/2011/05/31/whs-2011-add-in-deployment-package-upgrades.aspx</guid>
            <pubDate>Tue, 31 May 2011 07:00:04 GMT</pubDate>
            <comments>http://blog.tentaclesoftware.com/archive/2011/05/31/whs-2011-add-in-deployment-package-upgrades.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://blog.tentaclesoftware.com/comments/commentRss/116.aspx</wfw:commentRss>
        </item>
        <item>
            <title>Review: &amp;ldquo;WiX: A Developer&amp;rsquo;s Guide&amp;rdquo; by Nick Ramirez</title>
            <category>Development</category>
            <link>http://blog.tentaclesoftware.com/archive/2011/05/22/review-ldquowix-a-developerrsquos-guiderdquo-by-nick-ramirez.aspx</link>
            <description>&lt;p&gt;We don’t normally review products on this blog; there are plenty of other content providers that do great reviews, and we want to keep the focus here on Windows Home Server development. Despite that (maybe because of it), we think this one is definitely worth your time. &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Disclaimer: &lt;a href="http://www.packtpub.com/" target="_blank"&gt;Packt Publishing&lt;/a&gt; gave us a free copy of this eBook in December 2010 and asked us to review it.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;By now, it should be pretty clear that &lt;a href="http://blog.tentaclesoftware.com/search.aspx?q=wix"&gt;I really like WiX&lt;/a&gt; for building MSI packages. WiX may have a steep learning curve, but once you’re over that it’s a very powerful toolset that gives you fine-grained control over your final installer package.&lt;/p&gt;  &lt;p&gt;The problem is that there isn’t a great deal of WiX knowledge stashed away in our shared Google-memory, and most of the text out there relates to specific solutions for individual problems. I’ve mostly taught myself, with lots of trial and error.&lt;/p&gt;  &lt;p&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="wix-a-developers-guide-cover" border="0" alt="wix-a-developers-guide-cover" src="http://blog.tentaclesoftware.com/images/blog_tentaclesoftware_com/Windows-Live-Writer/Review-WiX_B0D6/wix-a-developers-guide-cover_3.png" width="270" height="346" /&gt;&lt;/p&gt;  &lt;p&gt;With &lt;em&gt;“&lt;a href="http://www.packtpub.com/wix-a-developers-guide-to-windows-installer-xml/book" target="_blank"&gt;WiX: A Developer's Guide to Windows Installer XML&lt;/a&gt;”&lt;/em&gt;, Nick Ramirez has put together a consolidated, concise, and concrete walk-through of the major features in WiX 3.0 in a way I haven’t seen anywhere else.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Note: &lt;a href="http://wix.codeplex.com/releases/view/60102" target="_blank"&gt;WiX 3.5 was released&lt;/a&gt; at the end of January this year and brings Visual Studio 2010 and native IIS 7 support to WiX. Fortunately, there aren’t any major breaking changes (that I could find!) between 3.0 and 3.5, so all the learning you do on WiX 3.0 is applicable to 3.5 as well.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Nick starts out with the very basics, and doesn’t assume any prior knowledge beyond knowing how to open Visual Studio and edit XML files. You’re guided through the install of WiX and the creation of your very first WiX installer project. &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Note: Nick does call this out at the beginning of the book, but I think it’s worth restating: &lt;strong&gt;WiX only integrates with Visual Studio Standard Edition or higher, it does not integrate with Visual Studio Express&lt;/strong&gt;. You can still create installers without Visual Studio Standard, however, and Nick covers using command line tools to do that in a couple of chapters.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;From there, Nick moves into progressively more advanced topics. I like the way the book is structured in this way; you’re working with a functional installer after the first chapter, and you add more complex and shiny options iteratively, rather than being dumped into chapters full of reference material.&lt;/p&gt;  &lt;p&gt;I especially liked the way Nick covers areas that cause new WiX users lots of problems:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Installing files into the Global Assembly Cache (GAC)&lt;/li&gt;    &lt;li&gt;Setting file permissions and creating users &lt;/li&gt;    &lt;li&gt;Using custom properties and conditions &lt;/li&gt;    &lt;li&gt;Searching for files and registry keys on the machine during install &lt;/li&gt;    &lt;li&gt;Writing registry keys &lt;/li&gt;    &lt;li&gt;Installing and controlling Windows Services &lt;/li&gt;    &lt;li&gt;Localizing installers &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;There are plenty of code samples and screenshots in the right places, and Nick spends a good chunk of his text explaining exactly &lt;em&gt;why&lt;/em&gt; you should use specific options or variables rather than just &lt;em&gt;how&lt;/em&gt; to use them.&lt;/p&gt;  &lt;p&gt;While Nick caters for WiX-newbies, there’s still plenty of information of value to developers who’ve been up to their elbows in WiX for years. There’s even new stuff for us; we’re restructuring many of Tentacle Software’s installers based on Nick’s recommendations.&lt;/p&gt;  &lt;p&gt;The book weighs in at 316 pages, not including the index, and Packt is currently offering 15% off the retail price for the eBook version, which comes out to US$33.99 at the time of writing. You’ll make that back in the first hour by avoiding the will-sapping trawl through page after page of WiX forum threads, and you’ll save your hairline from hours of frustration.&lt;/p&gt;  &lt;p&gt;If you’re building applications for Windows Home Server (or any Windows product), it’s critical that you get the installer right. The installer creates your users’ first and last impression of your product; if it’s crap, users will think your application is crap too. &lt;/p&gt;  &lt;p&gt;We highly recommend &lt;em&gt;“&lt;/em&gt;&lt;a href="http://www.packtpub.com/wix-a-developers-guide-to-windows-installer-xml/book" target="_blank"&gt;&lt;em&gt;WiX: A Developer's Guide to Windows Installer XML&lt;/em&gt;&lt;/a&gt;&lt;em&gt;”&lt;/em&gt; because it’ll help reduce the number of crap installers lurking out there on the Internet. You really don’t want to be the guy who deletes core system files when your application uninstalls.&lt;/p&gt;&lt;img src="http://blog.tentaclesoftware.com/aggbug/115.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Sam Wood</dc:creator>
            <guid>http://blog.tentaclesoftware.com/archive/2011/05/22/review-ldquowix-a-developerrsquos-guiderdquo-by-nick-ramirez.aspx</guid>
            <pubDate>Sun, 22 May 2011 01:53:23 GMT</pubDate>
            <comments>http://blog.tentaclesoftware.com/archive/2011/05/22/review-ldquowix-a-developerrsquos-guiderdquo-by-nick-ramirez.aspx#feedback</comments>
            <wfw:commentRss>http://blog.tentaclesoftware.com/comments/commentRss/115.aspx</wfw:commentRss>
        </item>
        <item>
            <title>ASP.NET Routing and Default.aspx</title>
            <category>Development</category>
            <category>Microsoft</category>
            <link>http://blog.tentaclesoftware.com/archive/2011/04/07/asp-net-routing-and-default-aspx.aspx</link>
            <description>&lt;p&gt;If you’re using ASP.NET Routing (without the MVC abstractions), you’ll be trying to route &lt;a href="http://www.mysite.com/Default.aspx"&gt;http://www.mysite.com/Default.aspx&lt;/a&gt; sooner or later.&lt;/p&gt;  &lt;p&gt;This won’t work:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:c4e68bb4-6712-487b-ae88-38d94c156931" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public static void RegisterRoutes(RouteCollection routes)
{
    routes.Add("Default", new Route("Default.aspx", new RouteHandler("~/Site/Default.aspx")));
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It won’t work because the request isn’t actually for Default.aspx, the request is for the site root, which IIS will catch. IIS responds by attempting to serve the default page for the site (probably Default.aspx), which may or may not exist.&lt;/p&gt;

&lt;p&gt;To route requests to the site root, you’ll need to do this instead:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:812469c5-0cb0-4c63-8c15-c81123a09de7:3e004385-6f14-425c-8d16-4695e35ee784" class="wlWriterEditableSmartContent"&gt;&lt;pre name="code" class="c#"&gt;public static void RegisterRoutes(RouteCollection routes)
{
    routes.Add("Default", new Route(string.Empty, new RouteHandler("~/Site/Default.aspx")));
}&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We’re now handling requests for the site root (which will be an empty string, as far as the Routing engine is concerned), so IIS and the site’s default page are never invoked.&lt;/p&gt;

&lt;p&gt;You could use &lt;em&gt;RouteExistingFiles = true&lt;/em&gt;, but I prefer this solution. It more explicitly defines what you’re trying to accomplish, which is always better for readability.&lt;/p&gt;&lt;img src="http://blog.tentaclesoftware.com/aggbug/114.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Sam Wood</dc:creator>
            <guid>http://blog.tentaclesoftware.com/archive/2011/04/07/asp-net-routing-and-default-aspx.aspx</guid>
            <pubDate>Wed, 06 Apr 2011 22:01:16 GMT</pubDate>
            <comments>http://blog.tentaclesoftware.com/archive/2011/04/07/asp-net-routing-and-default-aspx.aspx#feedback</comments>
            <wfw:commentRss>http://blog.tentaclesoftware.com/comments/commentRss/114.aspx</wfw:commentRss>
        </item>
    </channel>
</rss>
