With SharePoint 2007, WSPBuilder became our standard packaging tool for SharePoint solutions. It was simple, powerful, and a damn site easier than trying to write your own manifest.
Well, SharePoint 2010 and Visual Studio 2010 followed later, and Microsoft introduced much better tooling of their own. However, we’ve still got a lot of code being packaged by WSPBuilder, and we didn’t want to have to refactor all those projects just to package them for 2010.
Fortunately, Carsten Keutmann wrote a 2010 version (still in ‘BETA’, but it works fine). It offers many of the same extensions to Visual Studio as the previous version did.
However, I recently had to automate (in Team Foundation Server 2010) the build of one of our WSPBuilder based solutions, and that’s where things got more interesting…
First off, let’s be clear, there are a couple of different issues here:
- What are the differences between a 2007 and a 2010 solution package?
- Can we integrate WSPBuilder into our build process in TFS?
I started by looking at the first question. I knew that my project – a little web part to display search results from Twitter – should work in 2010 without modification. So, on a SP2007 server, I packaged it using the WSPBuilder for 2007. I then installed the WSPBuilder Extensions for 2010 – these should still work for SP2007/VS2008 – and repackaged it. I compared the WSPs – and found that the manifests were different.
Ok, no problems there – a few bits in a different order, and the manifest shows compatibility to be 2007 and 2010. That’s cool.
Then on a SP2010 server, I took the same code and packaged it, and I then compared the two WSPs. There were different. The manifests were different:
Okay – so the solution tag is different (it has an extra attribute), and the line showing compatibility now shows SharePoint 2010 only as being compatible. I hadn’t changed my code at all, so the difference must be down to the server that it’s running on. I’d a hunch that if WSPBuilder was being run on a SP2010 server it would default to packaging for SharePoint 2010 only. However, WSPBuilder is pretty well thought out in the options you can feed in, so I figured that there must be an argument that I could feed in to tell it to package for 2007 or 2010 when being run on SharePoint 2010 server.
I was wrong. Eventually, I came across a series about “Porting a SharePoint 2007 WSPBuilder solution to SharePoint 2010” by Muhimbi where they said:
Note that if you want to use WSPBuilder to build a hybrid SharePoint 2007 / 2010 solution or a solution that just targets SharePoint 2007 then you must perform the build on a machine that runs SharePoint 2007. The latest version of WSPBuilder checks which version of SharePoint is installed on the build machine and adds SharePoint 2010 specific elements to the generated WSP file, causing deployments to fail in SharePoint 2007 environments.
Well, that’s what I was seeing. Just in case I checked the source on Codeplex. In the Keutmann.SharePoint.WSPBuilder.Library.ManifestConfig class, the choice between a SP2007 or SP2010 manifest seems to come from the registry – specifically, from checking the subkeys of SOFTWAREMicrosoftShared ToolsWeb Server Extensions . A “12” means SP2007, and a “14” means SP2010. There doesn’t seem to be an argument to pass in, and this means that if your build server has SP2010 installed on it – even if it isn’t configured – then all WSPs built on it will only be SP2010 compatible. Yuck.
It then occurred to me, could I install both the 2007 and 2010 versions of WSPBuilder? In short, no, the installer wouldn’t let me.
Okay, so, another thought – what if you don’t have SharePoint on the build server at all? Well, you’d have to put any assemblies you want to reference (like Microsoft.SharePoint.dll) into your TFS project, and reference them rather than the ones in 12 or 14 hive, but that’s not a problem. However, what would WSPBuilder do? Well, a quick test shows that it might well build it for SP2007 – and so be compatible with 2010 – but I’ve not really looked into it that far. It could be worth investigation; I gave up as I was unlikely to be allowed to remove SharePoint 2010 from our build server. For now, if I want automated builds to work for SharePoint 2007, we’ll need a second build server.
Phew! All of which led me around to the second question – how to integrate the packaging with the build server. I found some good posts about this by Brian Farnhill, but they were for Team Foundation Server 2008. His approach was to use a post-build event to run a little script, and in that script he a) copies the DLL to the correct location, and b) runs WSPBuilder. “Excellent”, I thought. It didn’t work.
It seems that the problem lies in the script itself; $(IsDesktopBuild) wasn’t returned what one would expect for Visual Studio 2010. So, instead, I came up with the following script:
if '$(BuildingInsideVisualStudio)' == 'true' GOTO LocalBuild
COPY "$(TargetDir)*.dll" "$(ProjectDir)bin$(ConfigurationName)"
"C:Program Files (x86)WSPToolsWSPBuilderExtensionsWSPBuilder.exe"
MOVE "$(ProjectDir)*.wsp" "$(TargetDir)WSPs"
"C:Program Files (x86)WSPToolsWSPBuilderExtensionsWSPBuilder.exe" -DeploymentTarget GAC
Excellent. $(BuildingInsideVisualStudio) does behave properly. I did find one quirk with this now, though – my solution was being packaged on a local build as if the assembly was being deployed to the BIN. Sadly, I needed it in the GAC (and this is how TFS was packaging it), and hence the argument to set the DeploymentTarget that you can see above.
Well, I now had my build working. However, the packaged solution was only compatible with SharePoint 2010. As it turned out, this was acceptable (there were other changes that we had to make for SP2010). If we wanted to package the 2007 version for 2007 deployment, though, we would need another build server as there doesn’t seem to be a way of telling WSPBuilder to ignore the fact that it’s on a SharePoint 2010 server.