PowerShell で SharePoint CSOM を使用する際の Tips

こんにちは、SharePoint サポートの秋山 雅裕 (makiyama) です。
 
今回の投稿では、SharePoint Server / SharePoint Online に対して、クライアント サイド オブジェクト モデル (以下、CSOM) をリモートで実行する PowerShell スクリプトを記述する際の Tips をご紹介します。
 
CSOM を使用することで、SharePoint にログインすることなくサイト コレクション配下のオブジェクトを操作するバッチなどを実装することが可能です。
また、PowerShell を使用することで、Visual Studio などをインストールすることなくスクリプトが実行できます。

 

<目次>

 

事前準備

対象となる SharePoint によって利用可能な API が異なるため、適切な CSOM のアセンブリを取得します。
SharePoint の更新に合わせて CSOM のアセンブリも更新されるため、定期的に最新版を確認、取得いただくことをお勧めします。

 

SharePoint Online

Nuget 版と Microsoft Download 版がありますが、Nuget 版の方が機能追加などの更新が早いため、こちらをご利用いただくことをお勧めします。

 

Nuget 版
タイトル : Microsoft.SharePointOnline.CSOM
URL : https://www.nuget.org/packages/Microsoft.SharePointOnline.CSOM/

 

Microsoft Download 版
タイトル : SharePoint Online Client Components SDK
URL : https://www.microsoft.com/en-us/download/details.aspx?id=42038

 

Get-SPOSite などのコマンドレットを合わせて使用する場合は、SharePoint Online Management Shell をインストールすることで、CSOM のモジュールもインストールされます。
なお、SharePoint Online Management Shell と SharePoint Online Client Components SDK などを同時にインストールした場合エラーが発生する可能性があるため、いずれかのみのインストールとしてください。

タイトル : SharePoint Online Management Shell
URL : https://www.microsoft.com/en-us/download/details.aspx?id=35588

 

SharePoint Server 2016

タイトル : SharePoint Server 2016 Client Components SDK
URL : https://www.microsoft.com/en-us/download/details.aspx?id=51679

 

SharePoint Server 2013

タイトル : SharePoint Server 2013 Client Components SDK
URL : https://www.microsoft.com/en-us/download/details.aspx?id=35585

 

SharePoint Server 2010

タイトル : SharePoint Foundation 2010 Client Object Model Redistributable
URL : https://www.microsoft.com/download/en/details.aspx?id=21786

 

- 参考情報
タイトル : Using correct Client Side Object Model (CSOM) version for SharePoint customizations
URL : https://dev.office.com/blogs/using-correct-csom-version-for-sharepoint-customizations
 
タイトル : SharePoint Online に対して PowerShell を使用する方法
URL : https://blogs.technet.microsoft.com/sharepoint_support/2014/10/19/sharepoint-online-powershell/
 
タイトル : クライアント オブジェクト モデルを使用したプログラミング 第 2 回 : フォームアプリケーションの作成
URL : https://blogs.technet.microsoft.com/sharepoint_support/2012/04/10/1251-2/

 

ツール

SharePoint に対するスクリプトを実装するにあたり、以下のようなツールをご利用いただけます。

- SharePoint 管理シェル (SharePoint Online Management Shell)
- PowerShell.exe
- PowerShell ISE

 

いずれも既定では CSOM のモジュールが読み込まれないため、IntelliSense が既定で利用できません。
※ IntelliSense とは、クラス名やメソッド名などの候補や途中まで入力して補完させる機能で、PowerShell は既に読み込まれているモジュールに対し、IntelliSense が有効となります。

CSOM に対する IntelliSense を有効化するには、以下の手順をご検討ください。

 

PowerShell.exe

以下のコマンドレットを実行します。

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client") | Out-Null [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime") | Out-Null

 

PowerShell ISE

PowerShell ISE を使用することでスクリプト ファイルの保存や IntelliSense、ブレーク ポイントを使用したデバッグなどが容易となります。

タイトル : Windows PowerShell ISE の紹介
URL : /ja-jp/powershell/scripting/core-powershell/ise/introducing-the-windows-powershell-ise?view=powershell-5.1
 
IntelliSense を有効化するには、下部のコンソール ウィンドウ (青い背景) にて以下のコマンドレットを実行します。

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client") | Out-Null [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime") | Out-Null
 
 
毎回実行したくない場合は、PowerShell ISE を起動する際に既定で CSOM のモジュールが読み込まれるよう構成できます。
ただし、作成したスクリプトを別の環境にて実行する際には CSOM のモジュールを忘れずに読み込むよう注意する必要があります。
 
既定で CSOM のモジュールを読み込むには以下の手順を実施します。
 
1. PowerShell ISE を起動します。
2. コンソール ウィンドウにて以下のコマンドレットを実行します。

if (!(test-path $profile )) { new-item -type file -path $profile -force } psEdit $profile

3. "Microsoft.PowerShellISE_profile.ps1" が開くので、以下を追記します。

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client") | Out-Null [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime") | Out-Null

4. ファイルを保存して PowerShell ISE を閉じます。
次回以降同じユーザーで PowerShell ISE を開くと、既定で CSOM のモジュールが読み込まれます。

 

基本的な CSOM の実装

PowerShell より CSOM を使用する際の、基本的なサンプルにつきましては、以下のブログをご参照ください。

タイトル : SharePoint Online に対して PowerShell を使用する方法
URL : https://blogs.technet.microsoft.com/sharepoint_support/2014/10/19/sharepoint-online-powershell/
参考箇所 : [方法 2. SharePoint Online Client Component SDK] セクション [PowerShell サンプル *.ps1]

 

また、CSOM の基本的な操作のサンプルにつきましては、以下の公開情報をご参照ください。

タイトル : SharePoint 2013 のクライアント ライブラリ コードを使用して基本的な操作を完了する
URL : https://msdn.microsoft.com/ja-jp/library/office/fp179912.aspx

 

ラムダ式の利用

上記公開情報のサンプルでは、ラムダ式を多用しています。
例として、[Web 内のすべての SharePoint リストを取得する] のサンプルを以下に抜粋します。
 
// Starting with ClientContext, the constructor requires a URL to the // server running SharePoint. ClientContext context = new ClientContext("https://SiteUrl");   // The SharePoint web at the URL. Web web = context.Web;   // Retrieve all lists from the server. context.Load(web.Lists,     lists => lists.Include(list => list.Title, // For each list, retrieve Title and Id.         list => list.Id));   // Execute query. context.ExecuteQuery();   // Enumerate the web.Lists. foreach (List list in web.Lists) {     label1.Text = label1.Text + ", " + list.Title; }
 
PowerShell ではラムダ式が使用できないため、上記と同様の処理を PowerShell で実装するには以下のように記述することとなります。
注) 実際は Title および Id の値は各リストをロードしなくても取得できますが、ロードが必要なプロパティを参照していると考えてください。
 
(悪い例) $context = New-Object Microsoft.SharePoint.Client.ClientContext("https://SiteUrl")   $web = $context.Web $context.Load($web.Lists) $context.ExecuteQuery()   foreach($list in $web.Lists) {     $context.Load($list)     $context.ExecuteQuery()       Write-Host "$($list.Title), $($list.Id)" }
 
ラムダ式を使用して 1 度でリスト コレクションをロードする C# と比べ、PowerShell ではリスト コレクションと各リストに対してロードする必要があります。
ExecuteQuery が呼ばれるたびに SharePoint との通信が発生するため、実行速度にかなりの差が発生します。
特に大量のリスト アイテムに対し毎回ロードを行った場合、数十分から数時間の差が発生する可能性があります。
 
PowerShell でラムダ式を使用するためには、Add-Type コマンドレットを使用して C# のコードを PowerShell で呼び出します。
 
(良い例) $clientAssembly = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client") $clientRuntimeAssembly = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime") $assemblies = ($clientAssembly.FullName, $clientRuntimeAssembly.FullName)   # ヘルパー メソッドの定義 Add-Type -Language CSharp -ReferencedAssemblies $assemblies -TypeDefinition " using Microsoft.SharePoint.Client;   public static class Helper {     public static void LoadListCollectionSample(ClientContext context, Web web)     {         context.Load(web.Lists,             lists => lists.Include(list => list.Title,                 list => list.Id));     } }"   $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) $web = $context.Web   # ヘルパー メソッドの呼び出し<br>[Helper]::LoadListCollectionSample($context, $web)   $context.ExecuteQuery()   foreach($list in $web.Lists) {     Write-Host "$($list.Title), $($list.Id)" }
 

実行速度以外のラムダ式を使用するメリットとして、ラムダ式を使用しないと取得できない HasUniqueRoleAssignments などのプロパティが取得可能となります。
 
- 参考情報
タイトル : Using CSharp (C#) code in Powershell scripts
URL : https://blogs.technet.microsoft.com/stefan_gossner/2010/05/07/using-csharp-c-code-in-powershell-scripts/
 
タイトル : クライアント オブジェクトの取得によって全プロパティが取得されるわけではない
URL : https://msdn.microsoft.com/ja-jp/library/office/ee534974(v=office.14).aspx
 
タイトル : SharePoint Online からサイト・リストの権限の一覧を取得するサンプル
URL : https://blogs.technet.microsoft.com/sharepoint_support/2015/04/04/sharepoint-online-1250/

 

ファイル出力

PowerShell よりファイルに出力する方法として、Out-File や Add-Content コマンドレットが用意されています。
ただし、これらのコマンドレットは毎回ファイルを開く、内容を書き込む、ファイルを閉じるといった処理を行います。
呼ばれる回数が少ない場合は問題ありませんが、大量のリスト アイテムの情報をテキスト ファイルに出力する場合など、繰り返し呼ばれる場合はパフォーマンスが問題になる可能性があります。
大量にファイルへの書き込みが発生する場合は、.NET Framework の StreamWriter を使用することをご検討ください。

 
(例) $writer = New-Object System.IO.StreamWriter("c:\work\out.txt", $true, [System.Text.Encoding]::utf8) $writer.WriteLine("テスト")   if($writer -ne $null) {     $writer.Flush()     $writer.Close()     $writer.Dispose() }
 
 

今回の投稿は以上になります。