Victor Vogelpoel

Excellence is in the details

PowerShell: Get-SPCField.ps1 – Getting SharePoint fields using Client Side Object Model

Leave a comment


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.

 

Advertisements

Author: Victor Vogelpoel

Dad, SharePoint technical specialist, PowerShell architect, photographer and just a guy whose life happens while trying planning it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s