Automating your Web Part builds (and distribution) with WPPackager and NAnt

I’m just finishing up the packaging for the new version of the SharePoint Forums Web Part tonight and thought I would share with you some ideas and concepts around the packaging and distribution of it.

Thanks to Paul Schaeflin who took time out of his busy schedule to put together a CAB installer for me. It was great but I thought I could improve on his foundation. I used that as a basis, but then went back to an additional friend, WPPackager. WPPackager is a sweet little tool that will package up your Web Part assemblies, resources, and additional files and create an MSI for you. The end user just runs the MSI without any fuss or mess screwing around with web.config or custom policy files. There’s a great MSDN article that explains how to use the tool with some examples. Check it out here.

Anyways, so I use NAnt for my builds (free, open source, blah, blah, blah) and with NAnt you can practically automate anything. Here’s part of my NAnt build file for SharePoint Forums:

    1 <?xml version="1.0"?>

    2 <project name="SharePoint Forums Web Part" default="deploy">


    4     <property name="" value="Debug" />

    5     <property name="output.dir" value="build" />

    6     <property name="deploy.dir" value="C:\Inetpub\wwwroot\bin" />

    7     <property name="resource.dir" value="C:\Inetpub\wwwroot\wpresources\BilSimser.SharePoint.WebParts.Forums" />

    8     <property name="wppackager.dir" value="C:\Program Files\WPPackager" />


   43     <target name="dist" description="create a distribution MSI for the web part" depends="build">


   45         <!-- Copy the files needed by WPPackager to the build directory -->

   46         <copy todir="${output.dir}" flatten="true">

   47             <fileset>

   48                 <include name="SharePointForums-" />

   49                 <include name="src\Manifest.xml" />

   50                 <include name="src\SharePointForums.dwp" />

   51             </fileset>

   52         </copy>


   54         <!-- Use WPPackager to create a MSI -->

   55         <exec program="WPPackager.exe" basedir="${wppackager.dir}" workingdir="${output.dir}">

   56             <arg value="SharePointForums-" />

   57         </exec>


   59     </target>


   61     <target name="install" description="installs the web part using the MSI installer" depends="dist">

   62         <exec program="SharePointForums-" basedir="${output.dir}" />

   63     </target>


   65 </project>

It’s fairly long and I’ve removed some of the targets for clarity but let’s break it down here. The default target is “deploy” which will in turn call “build” which first calls “clean”. These do what you think and deploy just copies the files to the “C:\Inetpub\wwwroot\bin” directory (or wherever you run your SharePoint server from).

The target we’re interested here is “dist”. The “dist” target will do three things:

  • Clean out the build directory and rebuild the system
  • Copy all the distribution files needed for the distribution
  • Execute the WPPackager.exe program and create an MSI

The build is done through the “build” dependency target which compiles the solution file but first executes the “clean” target which just deletes the build directory. All files are output first to the build directory (here specified as the variable ${output.dir}. This keeps all the dll files in one place rather than hunting all over for a Debug or Release directory.

The WPPackager program needs a single file which contains instructions to build the MSI. Here’s the SharePointForums- file:

    1 <?xml version="1.0" ?>


    3 <!--

    4     WPPackager file for SharePoint Forums Web Part

    5     Version

    6     GAC install

    7 -->


    9 <Wppackager xmlns="">


   11     <Manifest FileName="Manifest.xml" />


   13     <MSI

   14         Name="SharePointForums-"

   15         Version=""

   16         Manufacturer="Bil Simser" />


   18 </Wppackager>

Not much to look at. This just tells WPPackager that I’m building an MSI, giving it a name and version and manufacturer (that’s ME!). The Manifest.xml is the standard one from SharePoint that just lists the assemblies we’re including and the SafeControl entries (these are added to the web.config file auto-magically when the MSI is run).

The WPPackager needs all the files that are going into the distribution (much like if you were using a CAB project in Visual Studio to build a CAB) so the build script (using the “copy” task) copies the Manifest.xml and SharePointForums.dwp file from the Web Part directory into the build directory so WPPackager can find it when it runs.

Finally WPPackager is run using the “exec” task as shown here. This will create SharePointForums- in the output directory.

I also use an install target that will run the MSI after it’s built. I do this on a clean system just to test the build and install to make sure everything works (note to self: I’ll probably add an “un-install” target for rolling it back, if I can figure out how to execute the MSI backwards).

One note is on the output of WPPackager. You’ll see something like this:


     [copy] Copying 3 files to 'C:\dev\BilSimser.SharePoint\WebParts\ForumSingleSolution\build'.
     [exec] Success: MSI Installer: 'SharePointForums-' created successfully from 'SharePointForums-'.
     [exec] Note: 'SharePointForums-' is not signed. Consider signing 'SharePointForums-' so that the user can identify the source of the MSI.


Total time: 6.2 seconds.

The MSI that gets created is unsigned (and will be untrusted on the installing sever when it’s run). I didn’t want to get into the details of signing here but check out this article on using SignTool. Once you install SignTool you can do something like this in your build file:

signtool sign /a MyFile.msi

Which will sign the file with the best certificate it can find. I haven’t tried it so you’ll have to check it out yourself (I just need to get around to installing the Platform SDK, something I normally don’t do). Until then you’ll just have to trust me ;)

That’s about it for automating your distributions with NAnt. A similar build could be created with MSBuild and it’s format so I may create that when I move the project over to the 2007 platform later this month. Otherwise, with a few simple tools and commands you can have a nice little automated MSI builder so you don’t have to put your users through hell (like I did) on editing web.config files manually and trying to locate the “bin” folder (sorry about that guys).

BTW, WPPackager is being discontinued. Please read, speak up, and support the post here from Maurice Prather on it. Personally it’s a nice tool once you get to know it. It’s not perfect, but at least it a) creates an MSI for you b) inserts the SafeControl entries for you and c) will apply a custom policy file for you (it copies whatever is there and adds your own policy entries). Additionally, it will roll all this back all these changes when you un-install the Web Part from the Add/Remove Program Files menu. You could probably do the same with a custom installer but then you need to mess with the web.config file (finding the right node, adding entries to it, etc.) and backing up and creating custom policy files (as well as rolling this back during an un-install). Neither rocket nor science, but not just a few if/then/else statements either so WPPackager helps. A lot.

At this point, there’s no slick way I know of to install Web Parts in 2007 (yet), although Todd Baginski’s SharePoint Feature Manager is looking good, but it still needs things to manage and won’t install the Web Parts/Solutions for you. Hopefully someone will have something put together (perhaps a resurrection of WPPackager?) for 2007 as we really do need to in order to deliver packages to you, the consumer, and not have you go through crazy setups like in the past (or is it the present?).

Watch for the Web Part release later tonight on CodePlex.

No Comments