PowerShell – Loop through Sites, Content Types, Lists.


Many times before I have had to write a bit of PowerShell to loop through a SharePoint site fixing something up. When I start writing this script I normally start from scratch each time. Basically I need to perform the same basic looping functionality, and then either at the List level, content type level maybe even at the item level I need to perform some change.

For example, I might need to delete a certain field from every list of type event, or I need to set the default value on a column, or perhaps you just want to loop through the site to see what is where. Whatever the reason is, if the change needs to be made in many places, I will need to loop through the environment.

The order typically I loop through would be:

  • Web
  • Content Type
  • Lists
  • Content Types in Lists
  • Fields in Content Types
  • Items

Depending on what I was trying to achieve, I would either add, or remove extra sections going forward.

The code below is the basic template I would use to get me going.

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

#Functions
#Process the web Site, checking the Content Type at the web first before checking the Content Types at the list level.

function processWeb($web){
 #web
 $ctx.load($web)
 #Content Type
 $cts = $web.ContentTypes
 $ctx.load($cts)
 #Lists
 $lists = $web.Lists
 $ctx.Load($lists)
 $ctx.ExecuteQuery()
 #Display Web 
 write-host "Web Name:" $web.Title 
 processContentTypes($cts)
 processLists($lists)
}

#Loop through each content type
function processContentTypes($cts)
{
  foreach($ct in $cts)
  {
    Write-Host "Content Type:" $ct.Name             
    $ctx.Load($ct.FieldLinks);
    $ctx.ExecuteQuery();

    processFieldsLinks($ct.FieldLinks)
  }
}

#Loop through fields
function processFieldsLinks($fieldsLinks)
{
  foreach($f in $ct.FieldLinks)
  {
      Write-Host "Field " $f.Name 
  }
}

#Loop through each item
function processItems($items)
{
 foreach($item in $items)
 {
  if($item.FieldValues["Title"] -eq $null)
  {
   write-host "Item FileLeafRef: " $item.FieldValues["FileLeafRef"]
  }
  else
  {
   write-host "Item Title: " $item.FieldValues["Title"]
  }
 }
}

#Loop through each list in the site
function processLists($lists){
 foreach($list in $lists)
 {
  $ctx.load($list)
  $ctx.load($list.ContentTypes)
  $query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery(10000, 'UniqueId','ID','Created','Modified','FileLeafRef','Title')

  $listItems = $list.GetItems($query);
  $ctx.load($listItems)
  $ctx.ExecuteQuery();

  write-host "BaseTemplate: " $list.BaseTemplate " List: "$list.Title
  processContentTypes($list.ContentTypes)
  processItems($listItems)
 }
}

#Get the URL, and an account to log in with. (Needs permissions across the sites to make changes)
$webUrl = Read-Host -Prompt "Enter the URL of your Root site" 
$username = Read-Host -Prompt "Enter your Email login"
$password = Read-Host -Prompt "Password for $username" –AsSecureString

#Create Context and load sites.
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($webUrl)
$ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)

$rootWeb = $ctx.Web
$childWebs = $rootWeb.Webs
$ctx.Load($rootWeb)
$ctx.Load($childWebs)
$ctx.ExecuteQuery();

#Process the rootweb
processWeb($rootWeb)

#process the child webs
foreach($childWeb in $childWebs)
{
 processWeb($childWeb);
}

#complete
Write-Host "******Completed*********" -ForegroundColor Green

Just to give an example of how I might adjust this, if I wanted to only loop through lists that are Site Pages, with BaseTemplate of 119, I would change the processLists() function to only process the list if the BaseTemplate is 119.

#Loop through each list in the site
function processLists($lists){
 foreach($list in $lists)
 {
   $ctx.load($list)
   $ctx.ExecuteQuery()

   if($list.BaseTemplate -eq 119)
   {
     $ctx.load($list.ContentTypes)
     $query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery(10000, 'UniqueId','ID','Created','Modified','FileLeafRef','Title')
     $listItems = $list.GetItems($query);
     $ctx.load($listItems)
     $ctx.ExecuteQuery();

     write-host "BaseTemplate: " $list.BaseTemplate " List: "$list.Title
     processContentTypes($list.ContentTypes)
     processItems($listItems)
   }
 }
}

Link to file in OneDrive: http://1drv.ms/1V5Q8j8

Advertisements