PowerShell Scripts

11 minute read

During my current project we are using a lot of PowerShell scripts to administrate the environment and make development easier for us.

In this post that I will try to update frequently, I will share some of our useful PowerShell scripts.

Disabling or Enabling Access Request

Within our project we had an application with about 400 sites. All of these sites still had the Access Request enabled. We needed to disable these access requests. For this we created a PowerShell function you can use to enable and disable access requests.

###
# Function for enabling and disabling site access requests
###
function Set-AccessRequest{
    [CmdletBinding()]
	param (
		[string] $siteUrl = $(Read-Host -prompt "Site Url"),
        [bool] $enable  =[System.Convert]::ToBoolean($(Read-Host -prompt "Enable Access Requests")),
        [string] $email = $(Read-Host -prompt "Email")
	)
   
    $web = Get-SPWeb $SiteUrl;

    if($enabled){
        Write-Host "Enabling Site Access Requests for site: " $web.Url " for email: " $email -ForegroundColor Green;

        $web.RequestAccessEmail = $email;
    }else{
        Write-Host "Disabling Site Access Requests for site: " $web.Url -ForegroundColor Green;

        $web.RequestAccessEmail = "";
    }

    $web.Update();
}

 

Publish files within a site collection

In some situations you would like to have the ability to publish all files within a specific site collection. For example right before going live with a SharePoint publishing portal you need to be sure that every file is published or else end users could  get a access denied on certain resources.

###
# Function for Publishing files in SharePoint
###
function Publish-FilesInList(){
    param
    (
        [string] $siteUrl = $(Read-Host -prompt "Site Url"),
        [bool] $checkIn = $(Read-Host -prompt "CheckIn when file is CheckedOut"),
        [bool] $debug = $(Read-Host -prompt "Run Debug mode")
    ) 

    Start-SPAssignment -Global
    $site = Get-SPSite $siteUrl
    Write-Host "- Publishing files for the Site Collection:" $site.Url -ForegroundColor Cyan

    foreach($web in $site.AllWebs){
    
        Write-Host " - Publishing files for the Web:" $web.Url -ForegroundColor Cyan
        
        foreach($list in $web.Lists){
            if(!$list.Hidden -And !$list.IsPrivate -AND !$list.IsApplicationList -AND $list.BaseType -eq 1){
                Write-Host "  - Publishing files for the List:" $list.Title -ForegroundColor Cyan
                ProcessFolderGetFiles $list.RootFolder $debug
            }else{
                Write-Host "List is Private, ApplicationList, Hidden or no document library: " $list.Title -ForegroundColor Magenta
            }
        }
    }

    Stop-SPAssignment -Global
}

function ProcessFolderGetFiles(){
    param(
        $folder,
        $debug
    )
    if($debug){Write-Host "    - Processing Folder:" $folder.Name -ForegroundColor Cyan}

    foreach($file in $list.RootFolder.Files){
        if($debug){Write-Host "     - Publishing file:" $file.Name -ForegroundColor Cyan}
        if ($file.Level -ne "Published"){
            if (($file.Level -eq "Checkout" -or $file.CheckOutStatus -ne "None")-and $checkIn){
                Write-Host "      - File is checkedout" -ForegroundColor Yellow
                if($checkIn){
                    Write-Host "     - CheckingIn File" -ForegroundColor Yellow
                    $file.CheckIn("CheckingIn", [Microsoft.SharePoint.SPCheckinType]::MajorCheckIn);
                    $file.Publish('Published using Motion10 Powershell Module');
                    Write-Host "      - File Published" -ForegroundColor Yellow
                }
            }else{
                $file.Publish('Published using Motion10 Powershell Module');
                Write-Host "      - File Published" -ForegroundColor Yellow
            }

            $file.Update();
        }else{
            if($debug){Write-Host "      - File already published" -ForegroundColor Cyan}
        }
    }
    # Use recursion to loop through all subfolders.
    foreach ($subFolder in $folder.SubFolders){
       ProcessFolderGetFiles($Subfolder)
    }
}

Unregister a Custom Claim Provider for a specific zone in a web application

There are situations were for you will develop custom claim providers. These claim providers can be installed globally on the farm but can also be installed for a specific zone in a web application. The following script will allow you to unregister a custom claim provider for a zone.

function Unregister-CustomClaimProvider{
	param(
		  [string] $DisplayName = $(Read-Host -prompt "Claim Provider Display Name"),
		  [string] $Url = $(Read-Host -prompt "Web Application Identity"),
		  [string] $InternalName = $(Read-Host -prompt "Claim Provider Internal Name"),
		  [string] $Zone = $(Read-Host -prompt "Zone")
	)

	
	$WebApplication = Get-SPWebApplication $Url 
	if ($WebApplication.IisSettings.ContainsKey($Zone)){
		$settings = $WebApplication.GetIisSettingsWithFallback($zone)
		$providers = $settings.ClaimsProviders;
		if($providers.Contains($InternalName)) {
			Write-Host "Claim Provider is registerd in this zone trying to remove..." -ForegroundColor Green
			$providers.Remove($InternalName);
			Set-SPWebApplication -Identity $WebApplication -Zone $Zone -AdditionalClaimProvider $providers
		}else{
			Write-Host "$DisplayName is not registered on $($WebApplication.Url) in zone $Zone" -ForegroundColor Yellow
		}
	}
}

Disable Browser Based Editing for Sites under a Specific Url

In certain situations you would like to disable all browser based editing for specific sites within SharePoint. With the below PowerShell script you can disable browser based editing.

Get-SPSite -WebApplication [Web Application] -Limit ALL | where {$_.Url.StartsWith("[Url start With]") } | Foreach-Object { 
    Write-Host "Activating Feature Client Based Editing for site" $_.Url
    Enable-SPFeature –identity 8a4b8de2-6fd8-41e9-923c-c7c3c00f8295 -URL $_.Url
}

Warm Up SharePoint 2013 Site Collections

When you maintain SharePoint environments you would like to warm up the environments for example once a day. The first load on SharePoint still takes a lot of time. For this situation I have developed a warm up script that also take in account your extended Host Named Site Collections.

function WarmUp-Url([string]$url){
    Write-Host "Warming up " $url -ForegroundColor DarkYellow;
    Invoke-WebRequest $url -UseDefaultCredentials -UseBasicParsing; 
}

foreach ($WebApp in (Get-SPWebApplication -IncludeCentralAdministration)){
    $sites = $WebApp | Get-SPSite -Limit All | Get-SPWeb -Limit All
        foreach($site in $sites){
            $html= WarmUp-Url -url $site.Url 
        
            if($site.IsRootWeb){
                $extendedurls = Get-SPSiteURL $site.Url  -ErrorAction SilentlyContinue;

                foreach($url in $extendedurls){
                    if($url.Url -ne $site.Url){                        
                        $html = WarmUp-Url -url $url.Url;
                    }
                }
            }
        $site.Dispose();
    }   
}

Publish Content Types for Specific group

When you start working with the Content Type Hub in SharePoint you will get in situations were you would like to publish multiple content types at once. In these situations you could use the below function to publish all the content types in a specific group.

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
function Publish-ContentTypesForGroup {
    param
    (
        [parameter(mandatory=$true)][string]$hubUrl,
        [parameter(mandatory=$true)][string]$group
    ) 

    $site = Get-SPSite $hubUrl

    if(!($site -eq $null))
    {
        $contentTypePublisher = New-Object Microsoft.SharePoint.Taxonomy.ContentTypeSync.ContentTypePublisher ($site)
        $site.RootWeb.ContentTypes | ? {$_.Group -match $group} | % {

            if($_.ReadOnly){
                Write-Host "Content Type" $_Name " is Read Only" -ForegroundColor Yellow;
                $_.ReadOnly = $false;
                $_.Update();
            }
            $contentTypePublisher.Publish($_)
            write-host "Content type" $_.Name "has been republished" -foregroundcolor Green
        }
    }
}

Starting the Content Type Subscriber Job

When you work a lot with the Content Type Hub in SharePoint you would also like to start the Content Type Subscriber job by using PowerShell. The below script does the job the web application you specify.

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
function Run-SPContentTypeHubJob([string]$url) 
{ 
    $job = Get-SPTimerJob -WebApplication $url | ?{ $_.Name -like "MetadataSubscriberTimerJob"} 

    if ($job -ne $null)  
    {   
        Write-host "The timerjob will be started....." -ForeGroundColor Green
        $job | Start-SPTimerJob 

        Write-host  "Run the admin job..." -ForeGroundColor Green
        Start-SPAdminJob -ErrorAction SilentlyContinue              
    }
    else{
	Write-Host "The Job could not be found" -ForeGroundColor Red
    }
}

Delete all items in a List

During many projects I had situations were I had to remove all items in a list. In this situation you can choose for removing the complete list en recreating it or you could delete every single item. With the below function you can delete every item in the list.

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
function Clear-SPList {
    param
    (
        [parameter(mandatory=$false)][string]$siteUrl,
        [parameter(mandatory=$false)][string]$listname
    )

    $site = Get-SPSite $siteUrl;
    $web = $site.OpenWeb();
    $list = $web.Lists[$listname];

    write-host "Clearing SharePoint list: " $list.Title -ForeGroundColor Green

    $collListItems = $list.Items;
    $count = $collListItems.Count - 1;
    for($intIndex = $count; $intIndex -gt -1; $intIndex--)
    {
            $collListItems.Delete($intIndex);
    } 
}

Finding content types that use a specific field

It ofton occurs that you would like to delete a site column but can't because it is used by a specific content type. It really takes a long time then to find the right content type. Using the below PowerShell function it is easy and fast to find your content type.

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
function Find-ContenttypesByField {
    param
    (
        [parameter(mandatory=$false)][string]$siteUrl,
        [parameter(mandatory=$false)][string]$fieldname
    )

  $site = Get-SPSite $siteUrl
  $web = $site.RootWeb;
  $fields = $web.Fields;

  $guid = $fields[$fieldname].id;

  $ct = $web.AvailableContentTypes 
  for ($i=0; $i -lt $ct.count; $i++) 
  {
    for ($j=0; $j -lt $ct[$i].fields.count; $j++) 
    {
      if ($ct[$i].fields[$j].id -eq $guid)
      {
        Write-host $ct[$i].Name " has column";
      }
    }
  }
}

Setting up Ping and SharePoint Trust Federation

For a environment we wanted to setup a SSO environment with for example K2. The most know situation is using ADFS. But at our client we were required to use Ping. The configuration an the SharePoint site looks very much the same as ADFS. For a reference I have included the PowerShell script in this post.

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

$certpath  = "[Ping Certification Path]"
$stsname   = "Auth-iLink"
$stsdesc   = "PingFederate Claims Provider SharePoint"
$stsrealm  = "sharepoint:ping:con"  #realm configured on Ping
$signinurl = "[URL Ping]/idp/prp.wsf"

Write-host "Importing Certification on SharePoint Server (Trust relation)." -ForegroundColor Green
New-SPTrustedRootAuthority -Name "PingFederate IP-STS Sharepoint" -Certificate $certpath

Write-Host "Getting the Certification Object." -ForegroundColor Green
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certpath)

Write-Host "Setting up Claim Mapping for SharePoint Authentication" -ForegroundColor Green
$mappingRole = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/claims/Group" -IncomingClaimTypeDisplayName "Role" -LocalClaimType "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
$mappingName = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/claims/CommonName" -IncomingClaimTypeDisplayName "GivenName" -LocalClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"

Write-Host "Setting Up Token Issuer"
New-SPTrustedIdentityTokenIssuer -Name $stsname -Description $stsdesc -Realm $stsrealm -ImportTrustCertificate $cert -ClaimsMappings $mappingRole,$mappingName -SignInUrl $signinurl -IdentifierClaim $m2.InputClaimType

Write-Host "Trusted Identity Token Issuer is set up."

Delete empty sub folders

For a migration we had a large set of folder with also empty folders in it. During the migration we iterated trough the folders also going trough the empty folders took a lot of time for the migration process. That way we wanted a PowerShell script to delete the empty sub folders. (Remove the –whatif to actually perform the script).

Get-ChildItem -recurse | Where {$_.PSIsContainer -and `
@(Get-ChildItem -Lit $_.Fullname -r | Where {!$_.PSIsContainer}).Length -eq 0} |
Remove-Item -recurse -whatif

 

Delete site that start with a specific URL.

When you are using host named site collections within your environment and also build some kind provisioning mechanism (how this can be done with host named site collections can be read here). You will get in situations that you would like to remove a huge number of site collections that start with a specific URL. By using this script you can:

Get-SPSite -Limit ALL | where {$_.Url.StartsWith("http://spdev.com/sites") } | Foreach-Object { Remove-SPSite $_.Url –Confirm:$False
}

Flushing the blob cache

Because we are using the blob cache within our environment, we also need a easy option to clear the blob cache when we have update our style sheets or maybe JavaScript files.

Using this function you can easily clear the blob cache for a specific web application.

function Flush-SPBlobCache{
        param(
          [string] $Url = $(Read-Host -prompt "Web Application Identity")
        )        
        $webApp = Get-SPWebApplication $Url
        [Microsoft.SharePoint.Publishing.PublishingCache]::FlushBlobCache($webApp)
        Write-Host "Flushed the BLOB cache for:" $webApp
}

 

Feature upgrading

For upgrades on our solutions we use the standard upgrading framework of SharePoint. You can read about it here this is an article on the upgrading framework for SharePoint 2010 but it is also something for SharePoint 2013.

Using the following function you are able to upgrade a specific feature within a web application.

function Upgrade-SpecificFeatures{
        param(
          [string] $Url = $(Read-Host -prompt "Web Application Identity"),
          [Guid] $ID = $(Read-Host -prompt "Feature ID")