Sunday, March 29, 2015

Create and Compare a Source and Target Site Inventory using PowerShell

Let's say you're doing a SharePoint migration. You think you have everything. You've done some good spot checking and the migration tool says all your content is there. How can you really be sure? With PowerShell you can be 100% sure.

Now I want to give you a disclaimer: when migrating between different versions of SharePoint, you cannot expect absolute data parity. For example, the masterpage galleries are going to be different. Additionally, there's some new features that add new lists that we didn't have before. A lot of it depends on your site templates you're using in the target environment. Don't sweat the behind the scenes lists. Focus on your content.

Now that we have the disclaimer out of the way, here's how you can be sure that you have all the content. Run the script below against both your source and target environment. This script will get the list, the site, and the item name for all items. And when I mean all items, I mean everything. This includes, but is not limited to the masterpage gallery, workflow history lists, and SharePoint security groups too. Depending on the size of your site collection and the horsepower behind SharePoint, this script can take anywhere from minutes to a few hours to run.

2007

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

$url = "http://yoursitecollection.url"

$site = [Microsoft.SharePoint.Administration.SPWebApplication]::Lookup($url)



#Create array variable to store data

$siteitems = $null

$siteitems = @()

#Loop to collect Site, list, and list item

foreach ($web in $site.allwebs) 

        

            {Write-Host $web.url -foregroundcolor yellow ; 

                foreach($List in $web.lists)

                    {foreach($item in $List.Items)

                        {$props = @{'Site' = $web.Url;'List'=$List.Title;'Item'=$Item.Name} ; $siteitemarray = New-Object -TypeName PSObject -Property $props ; $siteitems += $siteitemarray  

                    

                        }

                    }

               }

#Output to CSV

$siteitems | Export-Csv c:\2007_Target_siteoutput.csv

2010/2013

Add-PSSnapin Microsoft.SharePoint.PowerShell

$url = "http://yoursitecollection.url"

$site = get-spsite $url

#Create array variable to store data

$siteitems = $null

$siteitems = @()

#Loop to collect Site, list, and list item

foreach ($web in $site.allwebs) 

        

            {Write-Host $web.url -foregroundcolor yellow ; 

                foreach($List in $web.lists)

                    {foreach($item in $List.Items)

                        {$props = @{'Site' = $web.Url;'List'=$List.Title;'Item'=$Item.Name} ; $siteitemarray = New-Object -TypeName PSObject -Property $props ; $siteitems += $siteitemarray  

                    

                        }

                    }

               }

#Output to CSV

$siteitems | Export-Csv c:\2010_2013_Target_siteoutput.csv

Once the scripts have completed they need to be compared. Place the CSV outputs from the scripts above onto the same server. Then run the script below.


$file1 = import-csv -Path "c:\2007_Source_siteoutput.csv" 

$file2 = import-csv -Path "c:\2010_2013_Target_siteoutput.csv"

Compare-Object -referenceobject $file1 -differenceobject $file2 -Property Site,List,Item -PassThru |Where-Object {$_.SideIndicator -ne "=="} | Export-csv C:\Comparison_output.csv NoTypeInformation

What the script above does is it compares the two files and creates a new column called "Side Indicator." What this new column allows you to do is filter by <= and =>. Filtering by <= means this file is in the source site but not the target site, whereas filtering by => means the file is in the target site but not the source site. This will easily allow you to filter and find out what's missing and move it into the target environment.

The scripts above works for getting the inventory of a site collection. But what if you're migrating an entire web app? You can create an inventory using the script below. 

Add-PSSnapin Microsoft.SharePoint.PowerShell

$url = "http://yoursitecollection.url"

$site = get-spsite $url

#Create array variable to store data

$siteitems = $null

$siteitems = @()

#Loop to collect Site, list, and list item

Foreach($site in $SPWebApplication.Sites)

	{

		foreach ($web in $site.allwebs) 

            {Write-Host $web.url -foregroundcolor yellow ; 

                foreach($List in $web.lists)

                    {foreach($item in $List.Items)

                        {$props = @{'Site' = $web.Url;'List'=$List.Title;'Item'=$Item.Name} ; $siteitemarray = New-Object -TypeName PSObject -Property $props ; $siteitems += $siteitemarray  

                    

                        }

                    }

               }

	}

#Output to CSV

$siteitems | Export-Csv c:\WebApp_Output.csv

These scripts have saved the day a few times and credit is due to PowerShell jockey Eric Criniere for the scripts.