Sunday, January 24, 2016

Add custom javascript file to all pages in Sharepoint Online site collection

In my previous post (see Add custom javascript file to all pages in on-premise Sharepoint site collection without modifying masterpage) I showed how to inject custom javascript file to all pages on all sites in all site collections of specified web application without modifying master page. In this post I will show how to do the same using client object model for Sharepoint Online. For enumerating all site collections in Sharepoint Online we will use technique described in my other post Enumerate all tenant’s site collections in Sharepoint Online via PowerShell. Here is PowerShell which adds custom javascript to all site collections on Sharepoint Online:

   1: param(
   2:     [string]$adminWebAppUrl,
   3:     [string]$login,
   4:     [string]$password
   5: )
   6:  
   7: $currentDir = Convert-Path(Get-Location)
   8: $dllsDir = resolve-path($currentDir + "\..\dlls")
   9:  
  10: [System.Reflection.Assembly]::LoadFile([System.IO.Path]::Combine($dllsDir,
  11:     "Microsoft.SharePoint.Client.dll"))
  12: [System.Reflection.Assembly]::LoadFile([System.IO.Path]::Combine($dllsDir,
  13:     "Microsoft.SharePoint.Client.Runtime.dll"))
  14: [System.Reflection.Assembly]::LoadFile([System.IO.Path]::Combine($dllsDir,
  15:     "Microsoft.SharePoint.Client.Taxonomy.dll"))
  16: [System.Reflection.Assembly]::LoadFile([System.IO.Path]::Combine($dllsDir,
  17:     "Microsoft.Online.SharePoint.Client.Tenant.dll"))
  18:  
  19: Import-Module ..\spps\spps.psm1 
  20: Import-Module ..\spps\spps.subsites.psm1
  21:  
  22: if (-not $adminWebAppUrl)
  23: {
  24:     Write-Host "Specify admin web app url in adminWebAppUrl parameter" -foregroundcolor red
  25:     return
  26: }
  27:  
  28: if (-not $login)
  29: {
  30:     Write-Host "Specify user name in login parameter" -foregroundcolor red
  31:     return
  32: }
  33:  
  34: if (-not $password)
  35: {
  36:     Write-Host "Specify user password in password parameter" -foregroundcolor red
  37:     return
  38: }
  39:  
  40: function Upload-Script($ctx, $web)
  41: {
  42:     Write-Host "Upload script to Site Assets" -foregroundColor Green
  43:     $ctx.Load($web.Lists)
  44:     $ctx.ExecuteQuery()
  45:  
  46:     $assetsLib = $null
  47:     foreach ($l in $web.Lists)
  48:     {
  49:         if ($l.Title -eq "Site Assets")
  50:         {
  51:             $assetsLib = $l
  52:             break
  53:         }
  54:     }
  55:  
  56:     if (-not $assetsLib)
  57:     {
  58:         Write-Host "Sites Assets doclib not found. Script won't be uploaded" -foregroundcolor red
  59:         return
  60:     }
  61:  
  62:     $fileName = "foo.js"
  63:     $filePath = [System.IO.Path]::Combine($currentDir, $fileName)
  64:     if (-not [System.IO.File]::Exists($filePath))
  65:     {
  66:         Write-Host "File $filePath doesn't exist. It won't be uploaded" -foregroundcolor red
  67:         return
  68:     }
  69:  
  70:     $newFile = New-Object "Microsoft.SharePoint.Client.FileCreationInformation"
  71:     $newFile.Content = [System.IO.File]::ReadAllBytes($filePath)
  72:     $newFile.Url = $fileName
  73:     $newFile.Overwrite = $true
  74:     $uploadFile = $assetsLib.RootFolder.Files.Add($newFile)
  75:  
  76:     $ctx.Load($uploadFile)
  77:     $ctx.ExecuteQuery()
  78: }
  79:  
  80: function Add-Link($ctx, $web, $actionUrl, $sequence)
  81: {
  82:     Write-Host "Add custom action link" -foregroundColor Green
  83:     $existingActions = $web.UserCustomActions
  84:     $ctx.Load($existingActions)
  85:     $ctx.ExecuteQuery()
  86:  
  87:     $exists = $false
  88:     foreach($ac in $existingActions)
  89:     {
  90:         if ($ac.ScriptSrc.ToLower() -eq $actionUrl)
  91:         {
  92:             $exists = $true
  93:             break
  94:         }
  95:     }
  96:     
  97:     if ($exists)
  98:     {
  99:         Write-Host "Custom action is already added" -foregroundcolor Yellow
 100:         return
 101:     }
 102:  
 103:     $gaScript = $existingActions.Add()
 104:     $gaScript.Location = "ScriptLink"
 105:     $gaScript.ScriptSrc = $actionUrl
 106:     $gaScript.Sequence = $sequence
 107:     $gaScript.Update()
 108:  
 109:     $ctx.ExecuteQuery()
 110: }
 111:  
 112: function Add-Custom-Action($url)
 113: {
 114:     Write-Host "Adding custom action to $url" -foregroundColor Green
 115:     $clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($url)    
 116:     $clientContext.RequestTimeOut = 1000 * 60 * 10;
 117:     $clientContext.AuthenticationMode =
 118:         [Microsoft.SharePoint.Client.ClientAuthenticationMode]::Default
 119:     $securePassword = ConvertTo-SecureString $password -AsPlainText -Force
 120:     $credentials =
 121:         New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username,
 122:             $securePassword)
 123:     $clientContext.Credentials = $credentials
 124:     $web = $clientContext.Web
 125:     $site = $clientContext.Site
 126:     $clientContext.Load($web)
 127:     $clientContext.Load($site)
 128:     $clientContext.ExecuteQuery()
 129:  
 130:     Upload-Script $clientContext $clientContext.Web
 131:     Add-Link $clientContext $clientContext.Web "~sitecollection/SiteAssets/foo.js" 10001
 132: }
 133:  
 134: Start-Transcript -Path "output.log" -Append -Force -Confirm:$false
 135:  
 136: # initialize client context
 137: $clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($adminWebAppUrl)    
 138: $clientContext.RequestTimeOut = 1000 * 60 * 10;
 139: $clientContext.AuthenticationMode =
 140:     [Microsoft.SharePoint.Client.ClientAuthenticationMode]::Default
 141: $securePassword = ConvertTo-SecureString $password -AsPlainText -Force
 142: $credentials =
 143:     New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username,
 144:         $securePassword)
 145: $clientContext.Credentials = $credentials
 146: $web = $clientContext.Web
 147: $site = $clientContext.Site
 148: $clientContext.Load($web)
 149: $clientContext.Load($site)
 150: $clientContext.ExecuteQuery()
 151:  
 152: $tenant = New-Object "Microsoft.Online.SharePoint.TenantAdministration.Tenant" -ArgumentList $clientContext
 153: $props = $tenant.GetSiteProperties(0, $true)
 154: $clientContext.Load($props)
 155: $clientContext.ExecuteQuery()
 156:  
 157: foreach($sp in $props)
 158: {
 159:     Add-Custom-Action $sp.Url
 160: }
 161:  
 162: Stop-Transcript

In this script we at first enumerate all tenant site collections (lines 136-160). For each site collection we at first upload custom javascript file to Site Assets doclib (lines 40-78) and then add custom action with script reference on added javascript file (lines 80-110). As result our custom javascript file will be added to all pages in all site collections in Sharepoint Online web app.

No comments:

Post a Comment