Cette semaine, j’ai eu à oeuvrer sur une migration de données vers SharePoint Online. Nous devions créer en masse des bibliothèques de documents, définir des champs, y télécharger des fichiers et définir des métadonnées sur ceux-ci.
Dans un environnement on premises, c’est trivial, grâce à PowerShell et/ou aux API SharePoint. Initialement, nous avons utilisé les Web Services SharePoint mais ça reposait sur une application C# console, ce qui posait quelques complications :
- quand on a gouté aux API SharePoint, les Web Services sont assez pauvres
- les consultants qui devront utiliser l’outil et procéder aux migrations sont spécialisés en infrastructure et une application console est pour eux une “boite noire” qui impose d’avoir les sources, Visual Studio et de recompiler au besoin quand on a des changements à apporter
- les sources de données à migrer seront décrites dans des CSV. Pour les traiter en C#, point de gestion native ! Il faut soit coder un parser à la main soit trouver une bibliothèque existante qui s’en chargera.
Avec ces contraintes, mon choix s’est immédiatement porté sur le recodage de l’outil en PowerShell.
Outre ne plus avoir la “barrière de la langue” avec les non développeurs, le parsing de CSV en PowerShell est d’une grande simplicité :
$data = Import-Csv $csvPath -Encoding Default
Les API du Modèle Object Client SharePoint permettent de faire tout ce que nous avions à faire donc, nous les utiliserons.
Normalement, on se connecte sur SharePoint avec un object ClientContext. Dans Office 365, nous avons besoin de nous authentifier différemment. Le blog MSDN suivant non seulement nous indique la marche à suivre mais nous fournit une bibliothèque .NET pour gérer le tout :
http://blogs.msdn.com/b/sharepointdev/archive/2011/05/12/connecting-to-sharepoint-online-web-services.aspx
Les pré requis sont les suivant :
Le chargement des DLL se fait par réflexion :
$clientDlls = "Microsoft.SharePoint.Client.dll", "Microsoft.SharePoint.Client.Runtime.dll", "ClaimsAuth.dll"
$clientDlls | % { [void][Reflection.Assembly]::LoadFrom("$_") }
Une fois les API chargées, on ouvre un contexte SharePoint en appelant la méthode GetAuthenticatedContext :
$authContext = [MSDN.Samples.ClaimsAuth.ClaimClientContext]::GetAuthenticatedContext(“https://mytenant.sharepoint.com”)
Cette méthode ouvre une fenêtre de navigation (bloquant l’exécution du script tant qu’elle n'elle n’est pas fermée) qui permet à l’utilisateur de s’authentifier. Dès que l’utilisateur s’est connecté, la fenêtre se ferme et l’exécution du script se poursuit.
A noter : si on doit exécuter le script sur différents tenants depuis une même session Windows, il faut proprement se déconnecter du précédant tenant avant de vouloir s’authentifier sur le prochain sinon, quand on appelera GetAuthenticatedContext, la popup d’authentification ne se fermera pas et le context client sera mal initialisé faisant planter la suite du script !
L’utilisation du contexte client en PowerShell fonctionne presque de la même manière qu’en .NET classique. On prépare ses objets et collections d’objets puis on exécute ses requêtes.
$web = $authContext.Web
$authContext.Load($web)
$authContext.Load($web.Webs)
$authContext.Load($web.Lists)
$authContext.ExecuteQuery()
PowerShell n’étant pas ami avec les expressions lambdas et LINQ, on ne peut notamment pas utiliser LoadQuery.
Le reste du script fonctionne comme en .NET. Vous trouverez ci-dessous quelques exemples que j’ai utilisés.
Récupérer une liste par son nom
$list = $web.Lists.GetByTitle($entry.DocLibName)
$authContext.Load($list)
$authContext.ExecuteQuery()
Créer une liste
$listInfo = New-Object Microsoft.SharePoint.Client.ListCreationInformation
$listInfo.Title = $name
$listInfo.TemplateType = 101
$list = $web.Lists.Add($listInfo)
$authContext.ExecuteQuery()
Obtenir un object User
$user = $web.EnsureUser("i:0#.f|membership|toto@mytenant.onmicrosoft.com")
$authContext.Load($user)
$authContext.ExecuteQuery()
N.B.: Pour qu’un utilisateur soit accessible dans SharePoint, il faut qu’il ait une licence SharePoint Online associée.
Télécharger un fichier vers SharePoint
$fci = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$fci.Url = $documentUrl
$fci.Overwrite = $true
$fci.Content = [IO.File]::ReadAllBytes($localFilePath)
$documentFiles = $docSetFolder.Files
$authContext.Load($documentFiles)
$authContext.ExecuteQuery()
$newFile = $documentFiles.Add($fci)
$authContext.Load($newFile)
$authContext.ExecuteQuery()
J’espère que ce petit post vous sera utile !
SPierrick (PS et SP ne font qu’un !)