SharePoint 2013 And Office 365: Site And List Operations Using CSOM In PowerShell

During various SharePoint 2013 projects, I came across requirements which involve some bulk operations on existing SharePoint site. Here are some examples:

  • Creating many (100s) SharePoint Groups on a specific pattern.

  • Creating many lists and managing permissions on lists.

  • Managing list and/or item level permissions (breaking inheritance, assign permissions) in bulk.

  • Bulk add/edit operations in lists.

In these requirements, the major challenges are – (1) ‘No Access to Farm servers’; so we cannot write all logic in PowerShell script. (2) Long running bulk operations; so we cannot completely rely on client side java script.

The best approach is to create a hybrid solution and use PowerShell to connect to the site and then write logic using CSOM in script.

To use CSOM, we need to refer SharePoint client DLLs. So if we are running this script from a SharePoint 2013 machine, we can just refer from ISAPI folder. If running from a non-SharePoint machine, you need to copy these DLLs to machine and refer it in script.

In this example, script only covers connecting to a SharePoint site and reading list items. You can further add functions based on your requirement. The following are the steps to create this PowerShell Solution:

  1. Open Visual Studio and create a PowerShell project (refer my previous article for creating PowerShell projects in Visual Studio). Alternatively, you can use other PS editors like Power GUI.



  2. Rename the default script file to “ScriptMain.ps1”. Add a new script file “ConnectHelper.ps1”.



  3. Open “ConnectHelper.ps1” and copy the following code. There are generic methods to allow connection for both SharePoint 2013 on premises site and Online.
    1. ##Name: ConnectHelper.ps1#  
    2.   
    3. function Connect - SPClient { < #.This creates a Microsoft.SharePoint.Client.ClientContext object  
    4.     for a SharePoint site using the given credentials..Parameters - site, isSPOnline, user, password, requestTimeOutSec, formsBased, outputs.Example  
    5.     To create a ClientContext  
    6.     for an on - premises SharePoint using username and password  
    7.     $context = Connect - SPClient - site $site - user "domain\user" - password(ConvertTo - SecureString "password"–AsPlainText–Force) - isSPOnline: $false# > [CmdletBinding()]  
    8.     Param(  
    9.     [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String] $site, [Parameter(Mandatory = $false)][Boolean] $isSPOnline = $true, [Parameter(Mandatory = $false)][String] $user, [Parameter(Mandatory = $false)][SecureString] $password, [Parameter(Mandatory = $false)][int] $requestTimeoutSec = 180, [Parameter(Mandatory = $false)][Boolean] $formsBased = $false)  
    10.     Write - Host "$($MyInvocation.MyCommand.Name): Begin"  
    11.     Write - Verbose "$($MyInvocation.MyCommand.Name): Getting client connection to "  
    12.     "$site"  
    13.     " - $((Get-Date).toString())"  
    14.  
    15.     #Ensure required combination of user / password or sssSite / sssTargetAppId.  
    16.     if ([string]::IsNullOrEmpty($user) - or $password - eq $null) {  
    17.         throw "Invalid parameters. Provide both User and Password parameters. " + $user + " Password " + $password  
    18.     }  
    19.   
    20.     [System.Net.ServicePointManager]::ServerCertificateValidationCallback = {  
    21.         $true  
    22.     }  
    23.   
    24.     $context = New - Object Microsoft.SharePoint.Client.ClientContext($site) - Verbose: $false  
    25.   
    26.     if ($isSPOnline) {  
    27.         Write - Verbose "$($MyInvocation.MyCommand.Name): Generating SharePoint Online client credential"  
    28.         Write - Verbose "$($MyInvocation.MyCommand.Name): Creating credential from login/password"  
    29.         $context.Credentials = New - Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($user, $password) - Verbose: $false  
    30.   
    31.     } else {  
    32.         Write - Verbose "$($MyInvocation.MyCommand.Name): Generating Windows client credential"  
    33.         if ($formsBased) {  
    34.             Write - Verbose "$($MyInvocation.MyCommand.Name): Creating credential from login/password for forms based authentication"  
    35.             $context.AuthenticationMode = [Microsoft.SharePoint.Client.ClientAuthenticationMode]::FormsAuthentication  
    36.             $context.FormsAuthenticationLoginInfo = New - Object Microsoft.SharePoint.Client.NetworkCredential FormsAuthenticationLoginInfo($user, $password) - Verbose: $false  
    37.         } else {  
    38.             Write - Verbose "$($MyInvocation.MyCommand.Name): Creating credential from login/password for default authentication"  
    39.             $context.AuthenticationMode = [Microsoft.SharePoint.Client.ClientAuthenticationMode]::Default  
    40.             $context.Credentials = New - Object System.Net.NetworkCredential($user, $password) - Verbose: $false  
    41.             $context.add_ExecutingWebRequest($ {  
    42.                 function: ExecutingWebRequestEventHandler_NoFormsAuth  
    43.             })  
    44.         }  
    45.     }  
    46.  
    47.     #Set the timeout  
    48.     $context.RequestTimeout = ($requestTimeoutSec * 1000)  
    49.   
    50.     Write - Verbose "$($MyInvocation.MyCommand.Name):  Done"  
    51.     Write - Verbose "$($MyInvocation.MyCommand.Name): End"  
    52.     return $context  
    53. }  
    54.   
    55. function ExecutingWebRequestEventHandler_NoFormsAuth { < #.Synopsis  
    56.     This EventHandler must be used  
    57.     if authenticating against an on premise environment with mixed authentication(forms based + something differnt) to ensure that not forms based authentication is used.# > [CmdletBinding()]  
    58.     Param(#object sender, WebRequestEventArgs e[Parameter(Mandatory = $true)][object] $sender, [Parameter(Mandatory = $true)][Microsoft.SharePoint.Client.WebRequestEventArgs] $e)#Write - Host "$($MyInvocation.MyCommand.Name): ExecutingWebRequestEventHandler_NoFormsAuth"  
    59.     Write - Verbose "$($MyInvocation.MyCommand.Name): ExecutingWebRequestEventHandler_NoFormsAuth"  
    60.     $e.WebRequestExecutor.WebRequest.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED""f")  
    61. }  
  4. Open “ScriptMain.js” and copy this code. This define calling the connect methods with parameters and using CSOM, reading from list.
    1. < #.Synopsis  
    2. All main functions.Notes  
    3. Name: ScriptMain.ps1# >  
    4.  
    5. #Add references to SharePoint client assemblies - this is required  
    6. for CSOM  
    7. Add - Type - Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Taxonomy.dll"  
    8. Add - Type - Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"  
    9. Add - Type - Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"  
    10.  
    11. #Load connecthelper.  
    12. "$PSScriptRoot\ConnectHelper.ps1"  
    13.  
    14. #Global variables  
    15. $global: siteUrl = $null  
    16. $global: user = $null  
    17. $global: pass = $null  
    18. $global: isOnline = $null  
    19.   
    20. function SetCredentials() {  
    21.     $global: siteUrl = read - host "Enter Url"  
    22.     $global: user = read - host "Enter Username"  
    23.     $global: pass = read - host "Enter Password" - AsSecureString  
    24.     $global: isOnline = read - host "Is SPOnline(True/False)"  
    25. }  
    26.  
    27. #  
    28. function used to connect to SP Site  
    29.   
    30. function GetClientContext {  
    31.     [CmdletBinding()]  
    32.     Param(  
    33.     [Parameter(Mandatory = $true)][ValidateNotNullOrEmpty()][String] $siteUrl, [Parameter(Mandatory = $true)][String] $user, [Parameter(Mandatory = $true)][SecureString] $pass, [Parameter(Mandatory = $true)][String] $isOnline)  
    34.   
    35.     if ($isOnline - eq 'False') {  
    36.         $clientContext = Connect - SPClient - site $siteUrl - isSPOnline $false - user $user - password $pass  
    37.     } else {  
    38.         $clientContext = Connect - SPClient - site $siteUrl - isSPOnline $true - user $user - password $pass  
    39.     }  
    40.   
    41.     Try {  
    42.         $clientContext.Load($clientContext.Web);  
    43.         $clientContext.ExecuteQuery();  
    44.         Write - Host 'Connect to site:'  
    45.         $siteUrl - foregroundcolor green  
    46.         return $clientContext;  
    47.     } Catch[System.Exception] {  
    48.         Write - Host 'Unable to connect. Either invalid url or user and pass combination'  
    49.         return $null  
    50.     }  
    51. }  
    52.   
    53.   
    54. function Main() {  
    55.   
    56.     Write - Host 'Main Starts'  
    57.     $context = GetClientContext - siteUrl $global: siteUrl - isOnline $global: isOnline - user $global: user - pass $global: pass  
    58.   
    59.     if ($context - eq $null) {  
    60.         return  
    61.     }  
    62.   
    63.     Write - Host 'Load Shared Documets library';  
    64.   
    65.     $list = $context.Web.Lists.GetByTitle('Documents')  
    66.     $context.Load($list)  
    67.     $context.ExecuteQuery()  
    68.   
    69.     if ($list.ItemCount - le 0) {  
    70.         Write - Host 'There are no items inside Documents' - foregroundcolor red  
    71.         return  
    72.     } else {  
    73.         Write - Host 'Total Documents = '  
    74.         $list.ItemCount - foregroundcolor green  
    75.         return  
    76.     }  
    77. }  
    78.  
    79. ###Script Execution starts here#####Call Functions##  
    80. SetCredentials  
    81. Main  
  5. All the functions in both the scripts are self-explanatory. Please feel free to contact me if you have any doubts.

  6. Now, open the PowerShell console and change to the script directory. Call “ScriptMain.ps1” and hit Enter. It will ask for various parameters.



  7. Provide parameters: Site Url, User Name (domain\user), Password and IsSPOnline (True/False). Hit Enter.



  8. It will take few seconds to load SharePoint DLLs, and then will connect to the given site, read “Shared Documents” library item count and display.


I hope this will help.

Thanks!