How I Convinced SharePoints 2007 And 2010 To Play Nice On The Same Team Build Server

I broke the build this week. Without touching any code, for a project I wasn’t even working on.

SharePoint 2010 is still packing on its freshman fifteen. It’s a fair assumption that even if you are rocking this newer version of the collaboration platform, there is still plenty of MOSS 2007 / WSS 3.0 work being done within earshot. Add a shared resource like Team Foundation Server to the mix, and things can start to get interesting for the portal development team.

So there I was, well on my way to achieving automated check-in build goodness for my current SharePoint 2010 project. The good folks at MSDN have supplied instructions for just such an occasion, and I followed them to the proverbial T, availing the necessary version 14 assemblies to our TFS-sanctioned build machine. Shortly thereafter, my shiny new build was running green, and the hills were alive with the sound of continuous integration. Then, a knock at the entrance of my cubicle.

“Jon, do you know anything about this ‘SharePoint 2010 Reference Assemblies’ folder on the build server?”

Yes. Yes I did.

My colleague politely went on to explain that the build for their MOSS 2007 site had suddenly and mysteriously begun to break that afternoon. In reply, I donned the hair shirt and dug in to find a fix. Soon, I had arrived at a simple enough patch for this little inter-version SharePoint awkwardness, and I brought it here to share with you today.

The Key Is The Key

The most lightweight of all the changes recommended in the MSDN article was the addition of a single Registry key to the build server, indicating the location of the aforementioned SharePoint reference assemblies folder. I found that once this key was removed, the MOSS team’s build woes had dissolved, and mine had returned.

With no other build server available, the simplest solution was to add or remove the key from the server’s Registry at the start of each build, using a pair of .reg files and a command line call to regedit from within each build script.

This is the file used to add the key, for SharePoint 2010 builds:

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx\SharePoint14]@]
@="C:\\Program Files\\Reference Assemblies\\SharePoint"

And here, for SharePoint 2007 efforts, is the corresponding one used to remove the key:

Windows Registry Editor Version 5.00
[-HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx\SharePoint14]@]

Once those files have been created, you can add them directly to the appropriate solution by right-clicking on the Solution node in Visual Studio’s Solution Explorer pane, and selecting Add > Existing Item.

sp2007reg_thumb_2

sp2010reg_thumb_1

Assuming that your projects already have Team Builds configured, add a BeforeCompile Target to the TFSBuild.proj file in each, using the Exec task to merge the appropriate .reg file with a call to regedit /s, like this:

  <Target Name="BeforeCompile">
    <PropertyGroup>
      <RegFile>$(SolutionDir)\pre-build.reg</RegFile>
    </PropertyGroup>
    
    <!-- Merge the pre-build .reg file -->
    <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Message="Preparing Build Server">
      <Output TaskParameter="Id" PropertyName="StepId" />
    </BuildStep>
    <Exec Command="regedit /s &quot;$(RegFile)&quot;" />
    <BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)" Id="$(StepId)" Status="Succeeded" />
  </Target>

Now SharePoint 2007 and 2010 are building together, in perfect harmony. Just like in that Eddie Murphy /Joe Piscopo song.

Oh, All Right

Okay, it’s not perfect harmony. Should the builds coincide, one of them will fail, depending on who wrote to the registry last.

Nevertheless, there is something to be said for good enough. Especially when there are more important and less nerdy things to tighten down than the continuity and integrity of your continuous integration.

This Is How A Little jQuery Saved You From Using Hideous CSS Hacks

What I have here for you today is an unassuming snip of jQuery designed to circumvent the perils of the Browser-Specific CSS Hack. However tempting they may be to paste in for a quick fix, these disgusting pimples of software of are full of nasty preservatives that throw one’s humours into ill balance, and they do not belong in the style sheets of a professional-grade web site.

The code itself uses jQuery’s browserobject to build CSS class names out of the browser and version in use, and adds them to the page’s <body>tag.

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
 
    // get browser/version        
    var agent = "unknown";
    var version = $.browser.version.replace(/\./g, '-');
 
    if ($.browser.msie) agent = "msie";   // Microsoft Internet Explorer    
    else if ($.browser.mozilla) agent = "mozilla";    // Mozilla Firefox
    else if ($.browser.webkit) agent = "webkit"// Apple Safari or Google Chrome
    else if ($.browser.opera) agent = "opera";    // Opera            
 
    // add them as classes on the body tag   
    $(document).ready(function () {
        var body = $("body");
        body.addClass(agent);
        body.addClass(version);
    });
</script>

This then allows you, dear developer, to carve out browser/version-specific style attributes, while still leaving behind code that is human-readable and not at all reliant upon an instability in someone else’s software.

Behold—readable and precise browser dodging:

/* applied to all browsers */
ul.menu
{
    list-style:none;
}
/* applied to all versions of IE */
.msie ul.menu
{
    margin:5px;
}
/* applied to IE7 */
.msie.7-0 ul.menu
{
    list-style-image:none;
    margin:0px;
}
/* applied to the latest version of Chrome */
.webkit.6-0-472-53 ul.menu
{
    padding-top:-10px;
    border-radius:5px;
}