Using PowerShell for MOSS application deployment testing

Way back when the first Web browser, Mosaic, was just being born at NCSA at the University of Illinois, I was in college as well, and was running Linux. I was into Unix Shell scripting – csh, ksh, zsh, etc. Once I graduated, I switched to Windows and with the exception of a brief period of time working with Broadvision (yuck!) it’s been all Microsoft all the time. Professionally, I’ve always been a Microsoft developer and IT consultant. However, my experience with Unix shell scripting taught me the value of a rich shell language and for a long time the Dos/Windows command prompt seemed like a step down. Then PowerShell happened, and it was a whole new world. I’d read about PowerShell, and subscribed to the PowerShell blog, but didn’t really have much justification to use it. I used it once to create some test data files, and then just recently found a great use for it when deployment testing a SharePoint Application Pages application. My application used a .WSP solution file and several features to define and create about a dozen SharePoint lists in one site. During the feature deployment, most of those lists get prepopulated with data. A subsequent retract and delete of the solution though does not delete the lists. Also, in one list that I am using for configuration, I have the list item values set for the production environment and these settings are wrong for my development environment. PowerShell to the rescue.

First, I got Zach Rosenfield’s PowerShell script that provides access to SPWebs and SPSites (http://sharepoint.microsoft.com/blogs/zach/Lists/Posts/Post.aspx?ID=7), ran it, and then I did the following:

$rootweb = Get-SPWeb “http://moss.litwareinc.com”

for ($i=0; $i -lt $rootweb.Lists.Count; $i++) {

    $siteTitle = $rootweb.Lists[$i].Title;

    if($siteTitle -like “Site Pro*”)

    {

        $siteTitle;

        $rootweb.Lists[$i].Delete();

    }

}

$rootweb.Dispose();

Note that here all the lists that I wanted to delete began with a common prefix. Also, since I am deleting each list while looping through the collection of lists, the loop ends prematurely because the count of lists keeps decreasing. So I have to run the script a few times before it gets all the lists. But hitting up arrow and enter a few times took a lot less brain power and clicking than manually deleting each list. Eventually I unrolled the loop and just had it execute a handful of $rootweb.Lists[“<list name>”].Delete(); commands (one for each list I needed to remove).

For the SharePoint list that held my application settings, I had two settings that included the name of the staging environment (mosstest.litwareinc.com), while my development environment was called moss.litwareinc.com. Since this list and its data was instantiated fresh with each deployment, I could reference individual list items by ID, which would be the same after almost every build.

$rootweb = Get-SPWeb “http://moss.litwareinc.com/”

$listitem = $rootweb.Lists[“Site Provisioning App Settings”].Items.GetItemByID(11)

$listitem[“Value”] = $listitem[“Value”].ToString().Replace(“test”,””)

$listitem.Update()

$listitem = $rootweb.Lists[“Site Provisioning App Settings”].Items.GetItemByID(21)

$listitem[“Value”] = $listitem[“Value”].ToString().Replace(“test”,””)

$listitem.Update()

I included these scripts in my build process so that on every build of my SharePoint application, I compile all code, retract and delete the existing Solution and its features (deactivating them first if needed), delete the relevant lists, build the new WSP, install, deploy, and activate the solution and site level features and update one of the resulting lists.

The only downside is that it takes about 3 minutes for a complete build. This is inside a VM that uses 1GB of Ram, so it’s not the highest performance environment. That’s not the end of the world, but if you want to test a small code change, it’s annoying. I’m tempted to add build configurations where you have one configuration that does this whole process and one that just updates the DLLs.

–Michael