I am currently working on PowerShell scripts to ease SharePoint 2010/2013 configuration deployment in DTAP environments. These scripts started out with SharePoint Object Model (server side) dependencies, but in a discussion with Macaws SharePoint master Bram de Jager, I wondered if similar commands could be crafted with the SharePoint Client Site Object Model functionality as well. Goal is to create a proof of concept Get-SPField that uses SharePoint Client Object Model instead of the server SharePoint object model.
Upon arrival home Friday evening, I happily started my journey with SharePoint 2010 Client Site Object Model. The CSOM assemblies for SP2010 can be downloaded here. The setup installs the assemblies to C:Program FilesCommon FilesMicrosoft SharedSharePoint Client. I copied the Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.RunTime.dll assemblies to the same directory as my script and started typing away. Goal is to create a proof of concept Get-SPField that uses SharePoint Client Object Model instead of the server SharePoint object model. This is my first acquaintance with CSOM, so lets get the the Web object first as a test:
Add-Type -Path (Resolve-Path "Microsoft.SharePoint.Client.dll") Add-Type -Path (Resolve-Path "Microsoft.SharePoint.Client.Runtime.dll") # test CSOM via PowerShell $siteUrl = "http://sp2010Portal" $ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) $web = $ctx.Web # THROWS: System.Void Load(T clientObject, # Params System.Linq.Expressions.Expression[System.Func[T,System.Object]][] retrievals) # throws error: "Cannot find an overload for "Load" and the argument count: "1"." # Because PowerShell 2 is bad at generics $ctx.Load($web) $ctx.ExecuteQuery()
Unfortunately, SharePoint 2010 requires PowerShell v2 and PowerShell v2 doesn’t do generics well. $ctx.Load() yields an error: “Cannot find an overload for “Load” and the argument count: “1”.” I have a couple ideas to work around the problem, but I did not pursue this Friday evening.
Well, Bram already demonstrated with his SharePoint Client Browser for 2013 that PowerShell can easily query SharePoint 2013 instance on-premises or online. As PowerShell v3 is required for SP2013, apparently .NET generics in the $ctx.Load() is not a problem for PowerShell v3.
I downloaded the SharePoint 2013 Client Runtime assemblies from here and copied the Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.RunTime.dll assemblies (from folder C:Program FilesCommon Filesmicrosoft sharedWeb Server Extensions15ISAPI) next to my proof of concept script and fired up the PowerShell ISE 3. $PSVersionTable made sure that I was using PowerShell v3 in the editor.
# Test met SharePoint Client object model $loc = "D:\PowerShell" # Location of DLL's Set-Location $loc $siteUrl = "http://SP1013Portal" $loginname = "account" Add-Type -Path (Resolve-Path "Microsoft.SharePoint.Client.dll") Add-Type -Path (Resolve-Path "Microsoft.SharePoint.Client.Runtime.dll") Write-Host "Please enter password" $pwd = Read-Host -AsSecureString $spcCredentials = (New-Object -ErrorAction SilentlyContinue Microsoft.SharePoint.Client.SharePointOnlineCredentials($loginname, $pwd) ) function Get-SPCField { [CmdletBinding(SupportsShouldProcess=$false)] param ( [Parameter(Mandatory=$true, position=0, ValueFromPipeLineByPropertyName=$true, HelpMessage="Specifies the Web. The type must be a valid URL, in the form <a href="http://server_name">http: //server_name</a>, or a GUID, in the form 1234-5678-0987645a.")] [Alias("WebIdentity", "url")] [string]$WebUrl, [Parameter(Mandatory=$false, position=0, ValueFromPipeLine=$true, ValueFromPipeLineByPropertyName=$true, HelpMessage="TODO")] [Alias("ListName")] [string]$ListIdentity, [Parameter(Mandatory=$false, position=0, ValueFromPipeLine=$true, ValueFromPipeLineByPropertyName=$true, HelpMessage="TODO")] [Alias("FieldIdentity", "FieldName", "Id", "FieldId")] [string]$Identity = "*", [Parameter(Mandatory=$false, position=0, ValueFromPipeLine=$true, ValueFromPipeLineByPropertyName=$true, HelpMessage="TODO")] [Alias("GroupName")] [string]$Group = "*", [Parameter(Mandatory=$false, ValueFromPipeLineByPropertyName=$true, HelpMessage="TODO")] [Alias("Xml", "SchemaXml")] [switch]$AsSchemaXml ) process { $getListFields = ($PSBoundParameters["ListIdentity"] -ne $null) $ctx = New-Object Microsoft.SharePoint.Client.ClientContext($WebUrl) $ctx.Credentials = $spcCredentials if ($getListFields) { $list = $ctx.Web.Lists.GetByTitle($ListIdentity) $fields = $list.Fields } else { $fields = $ctx.Web.Fields } $ctx.Load($fields) $ctx.ExecuteQuery() Write-Output $fields | where { ($_.StaticName -like $Identity -or $_.Id -eq $Identity) ` -and $_.Group -like $Group } ` | foreach { if ($AsSchemaXml) { $_.SchemaXml } else { $_ } } } } # Fields from the web, as SchemaXml Get-SPCField –weburl "http://SP2013Portal" -AsSchemaXml #Fields from a list on the web, as SchemaXml Get-SPCField –weburl "http://SP2013Portal" -listidentity "contracten" -AsSchemaXml #Fields from a list on the web, select only staticname Get-SPCField -weburl "http://SP2013Portal" -listidentity "contracten" | select staticname
This could be very interesting: I’ll be creating more PowerShell script commands that ease configuration deployment using SharePoint client side object model after the server side versions have completed.