MOSS Site Info with PowerShell

I started working with a team on a large migration project a few months ago.  The client requested that we approach the migration site by site instead of upgrading the whole environment all at once.  The first phase of the project involved migrating STS to SharePoint 2010 (yes folks, I said STS... as in V1).  Phase two involves upgrading their MOSS environment to 2010 and that's the focus of this post.  We're trying to approach phase two in a similar fashion while keeping an eye on streamlining our processes. 

Overview of our Approach
Since we're approaching this project site by site, communication is VERY important.  I won't bore you with the details so here's the gist of the process.

1. We kick off a workflow which tosses our item into a Review state where we gather information about our sites (how big is the site, are there workflows or InfoPath forms, are there any other customization, etc).  **This is where PowerShell came in**
2. We contact the owner to schedule some time for the upgrade since their site will experience some downtime.
3. We perform the upgrade (with DocAve)
4. We verify the upgrade
5. We wait for site owner sign off

Enough of the Back Story Already!
The script is long and includes an options menu, error handling and logging so I'll just show the important parts.

We needed a list of all sites, the site owners, site size, and other information.  In order to use the object model, we need to load the SharePoint assembly.

[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

Get an instance of the needed SPWeb:
$site = New-Object Microsoft.SharePoint.SPSite($rootURL)
$web = $site.OpenWeb();

Get a list of people in the owners group:
    $owners = $null
    foreach ($u in $web.AssociatedOwnerGroup.Users)
    {
        $owners += $u.LoginName + ';'
    }
   
Next, I needed storage information for each site.   For more info on the following method, visit StorageManagementInformation

Get list storage information:
$listDataTable = New-Object System.Data.DataTable
$listDataTable = $s.StorageManagementInformation(1, "Increasing", "Size", "100000")

Get document storage information:
$docLibDataTable = New-Object System.Data.DataTable
$docLibDataTable = $s.StorageManagementInformation(2, "Increasing", "Size", "100000")

Get a total of list and library storage usage:
The previous lines created a data table that contained storage usage for each list and library.  Now we loop through each line and add up the numbers.  Since the data table contains usage for all lists and libraries in the site collection, we'll look for just the ones that are relevant to the current web by using the web's ID.

$siteSize = 0

foreach($row in $docLibDataTable.Rows)
{
     if (([Guid]$row.WebGuid) -eq ([GUID]$web.ID))
     {
           $siteSize += $row.Size
     }
}
       
foreach($row in $listDataTable.Rows)
{
     if (([Guid]$row.WebGuid) -eq ([GUID]$web.ID))
    {
           $siteSize += $row.Size
    }
}

Find running workflows and if an InfoPath form exists:
$availableWorkflows = $null
$containsInfoPathForms = $false
   
    foreach ($list in $web.Lists)
    {
        #if one infopath form is found on the site, there's no need to search again
        if ($containsInfoPathForms -eq $false)
        {          
            $containsInfoPathForms = ($list.BaseType -eq "DocumentLibrary" -and $list.BaseTemplate -eq "XMLForm")
        }
       
        foreach ($association in $list.WorkflowAssociations)
        {
            $availableWorkflows += $association.Name + ';'
        }
    }

 
Output the results to a CSV:
First, I needed a global variable to store the results since method that gathers all of the data is called recursively.

$global:outputToCsv = @()

Next, I create a new object to store the data for the current web and append those results to my global variable.

$output = New-Object PSObject
$output | Add-Member -MemberType NoteProperty -Name "Title" -Value $web.URL
$output | Add-Member -MemberType NoteProperty -Name Size -Value ($siteSize/1MB)
$output | Add-Member -MemberType NoteProperty -Name "Sub Sites" -Value $web.Webs.Count
$output | Add-Member -MemberType NoteProperty -Name "Infopath Forms" -Value $containsInfoPathForms

$output | Add-Member -MemberType NoteProperty -Name Owners -Value $owners
$output | Add-Member -MemberType NoteProperty -Name "Site Template" -Value $web.WebTemplate

$global:outputToCsv += $output
 
Finally, when all the data has been collected, I export it to a csv:

$global:outputToCsv | Export-Csv ("c:\scripts\OneSiteCollection.csv") -NoTypeInformation



Labels: