Transformer les pages classiques sélectionnées avec PnP PowerShell

L’outil d’évaluation Microsoft 365 inventorie les pages classiques, mais ne les modifie pas. Utilisez la sortie de l’évaluation pour approuver une vague de page et utilisez PnP PowerShell ConvertTo-PnPPage pour créer les pages modernes.

Remarque

PnP PowerShell est une solution open source pour laquelle un support est assuré par la communauté active. Il n’existe pas de contrat SLA Microsoft pour le support technique relatif à cet outil open source.

Workflow de transformation de page

  1. Sélectionnez une vague de page représentative à partir de la couverture d’évaluation terminée.
  2. Résolvez les composants WebPart bloquants et choisissez une cible sur place ou intersite.
  3. Préparez une application PowerShell PnP appartenant au client et les autorisations requises.
  4. Transformez la vague représentative avec des valeurs par défaut et une journalisation préservant le code source.
  5. Validez chaque page générée avant d’étendre la vague.

Avant de commencer

Remplissez ces conditions préalables :

  1. Exécutez et interprétez l’évaluation des pages classiques.
  2. Sélectionnez une vague représentative à partir d’une couverture d’analyse réussie.
  3. Installez PowerShell 7.4.0 ou version ultérieure et la version stable actuelle de PowerShell PnP.
  4. Inscrivez une application Microsoft Entra appartenant à un locataire pour un PowerShell PnP interactif.
  5. Vérifiez que l’utilisateur connecté peut modifier des pages dans les sites web source et cible.

Depuis le 9 septembre 2024, l’authentification PowerShell interactive PnP nécessite votre propre inscription d’application et votre propre ID client.

Le compte qui enregistre l’application doit être autorisé à créer des inscriptions d’applications. La stratégie de consentement du client détermine si un administrateur doit accorder le consentement.

Autorisations

Utilisez une application déléguée distincte de l’application d’évaluation en lecture seule.

Exigence de transformation Étendue SharePoint déléguée
Lire la source et créer, enregistrer et publier la page moderne AllSites.Manage
Copier également les autorisations uniques au niveau de l’élément AllSites.FullControl

Les autorisations de site de l’utilisateur connecté s’appliquent également. L’étendue déléguée de l’application n’accorde pas à l’utilisateur l’accès à un site auquel il ne pourrait pas accéder autrement.

Avec AllSites.Manage, ajoutez -SkipItemLevelPermissionCopyToClientSidePage pour que la page générée hérite des autorisations de sa bibliothèque. À utiliser AllSites.FullControl uniquement lorsque les autorisations uniques de la page doivent être conservées.

Installer ou mettre à jour PowerShell PnP

PowerShell PnP nécessite PowerShell 7.4.0 ou version ultérieure.

$PSVersionTable.PSVersion
Install-Module PnP.PowerShell -Scope CurrentUser

Si PowerShell PnP est déjà installé, exécutez-le Update-Module PnP.PowerShell à partir de PowerShell 7.4.0 ou version ultérieure.

Consultez Installer PowerShell PnP.

Inscrire l’application de transformation interactive

La commande suivante crée une application cliente publique pour une connexion interactive :

Register-PnPEntraIDAppForInteractiveLogin `
  -ApplicationName "Classic Page Transformation" `
  -Tenant "<tenant>.onmicrosoft.com" `
  -SharePointDelegatePermissions AllSites.Manage `
  -SignInAudience AzureADMyOrg

Copiez l’ID d’application renvoyé. Selon la stratégie de consentement du locataire, un administrateur peut avoir besoin d’accorder le consentement avant la première connexion.

Cette inscription de client public concerne la connexion interactive ou la connexion d’appareil déléguée. Il ne fournit pas les autorisations d’application ou le certificat requis pour l’authentification sans assistance.

Pour l’inscription manuelle et d’autres méthodes d’authentification, voir Enregistrer une application d’ID Entra pour PowerShell PnP.

Pour GCC High, DoD ou Microsoft 365 géré par 21Vianet, spécifiez la valeur correspondante -AzureEnvironment lors de l’inscription de l’application et de la connexion. Consultez les références des applets de commande Register-PnPEntraIDAppForInteractiveLogin et Connect-PnPOnline .

Mapper une ligne d’évaluation à PowerShell PnP

Champ d’évaluation Utilisation de PowerShell PnP
SiteUrl + WebUrl URL source du Connect-PnPOnlinefichier .
ListUrl, ListId, PageUrl Bibliothèque exacte et identité du SitePages fichier source.
PageType Doit être WikiPage ou WebPartPage pour ce flux de travail.
Layout Regroupement et validation de modèles représentatifs.

Avant de transformer une page de première vague, exiger :

  • Couverture réussie du site et du web.
  • PageType égal à WikiPage ou WebPartPage.
  • Aucun composant WebPart non résolu et non mappé.
  • WebPartCount Supérieur à 0. Gérez les pages sans partie en dehors de cet exemple automatisé après révision manuelle.
  • Page source qui hérite des autorisations de sa bibliothèque.
  • Une base de référence de contenu et de disposition enregistrée pour validation.

Créer des groupes de pages représentatifs

Le script suivant crée un inventaire des candidats. Il ne transforme pas les pages.

Il regroupe les pages Wiki et WebPart éligibles par type de page, mise en page et signature du composant WebPart ordonné. La signature comprend le type de composant WebPart, le résultat du mappage, l’état masqué et l’état fermé.

$pages = Import-Csv .\classicpages.csv
$webParts = Import-Csv .\classicpagewebparts.csv
$partsByPage = @{}

function Get-PageKey {
  param($Row)

  '{0}|{1}|{2}|{3}' -f $Row.ScanId, $Row.SiteUrl, $Row.WebUrl, $Row.PageUrl
}

foreach ($part in $webParts) {
  $key = Get-PageKey $part
  if (-not $partsByPage.ContainsKey($key)) {
    $partsByPage[$key] = [Collections.Generic.List[object]]::new()
  }

  $partsByPage[$key].Add($part)
}

$candidates = foreach ($page in $pages) {
  $fileName = [IO.Path]::GetFileName($page.PageUrl)

  if ($page.PageType -notin @('WikiPage', 'WebPartPage') -or
      $page.HomePage -eq 'True' -or
      -not $page.ListUrl.EndsWith('/SitePages', [StringComparison]::OrdinalIgnoreCase) -or
      $page.WebPartCount -eq '0' -or
      $page.MappingPercentage -ne '100' -or
      -not [string]::IsNullOrWhiteSpace($page.UnmappedWebParts) -or
      $fileName.StartsWith('Migrated_', [StringComparison]::OrdinalIgnoreCase) -or
      $fileName.StartsWith('Previous_', [StringComparison]::OrdinalIgnoreCase)) {
    continue
  }

  $key = Get-PageKey $page
  if (-not $partsByPage.ContainsKey($key)) {
    throw "Web Part rows are missing for $($page.PageUrl)."
  }

  $signature = (
    $partsByPage[$key] |
      Sort-Object { [int]$_.WebPartIndex } |
      ForEach-Object {
        '{0}|Mappable={1}|Hidden={2}|Closed={3}' -f
          $_.WebPartTypeShort, $_.IsMappable, $_.Hidden, $_.IsClosed
      }
  ) -join ';'

  [pscustomobject]@{
    PatternKey = '{0}|{1}|{2}' -f $page.PageType, $page.Layout, $signature
    ScanId = $page.ScanId
    SiteUrl = $page.SiteUrl
    WebUrl = $page.WebUrl
    PageUrl = $page.PageUrl
    PageType = $page.PageType
    ListUrl = $page.ListUrl
    ListId = $page.ListId
    AssessmentTimeZoneId = [TimeZoneInfo]::Local.Id
    Layout = $page.Layout
    HomePage = $page.HomePage
    WebPartCount = [int]$page.WebPartCount
    MappingPercentage = $page.MappingPercentage
    UnmappedWebParts = $page.UnmappedWebParts
    ModifiedAt = $page.ModifiedAt
    WebPartSignature = $signature
    IncludePattern = 'True'
    Selected = 'False'
    ExpectedVisibleContent = ''
    ValidationOwner = ''
  }
}

$groups = $candidates | Group-Object PatternKey -AsHashTable -AsString

$candidateInventory = foreach ($candidate in $candidates) {
  $candidate | Select-Object *,
    @{ Name = 'PatternPageCount'; Expression = { $groups[$candidate.PatternKey].Count } }
}

$candidateInventory |
  Sort-Object PatternKey, PageUrl |
  Export-Csv .\representative-page-groups.csv -NoTypeInformation

Passez en revue representative-page-groups.csv et sélectionnez au moins une page de chaque PatternKey contenu de la vague de migration. Sélectionnez des pages supplémentaires lorsque les propriétés du composant WebPart, le contenu lié ou le comportement de l’entreprise diffèrent sensiblement au sein d’un modèle.

Définissez IncludePattern=False pour les modèles en dehors de la migration planifiée. Pour chaque page sélectionnée, définir Selected=True et remplir ExpectedVisibleContent et ValidationOwner.

Exécutez l’étape de regroupement sur la même machine que celle qui a généré les CSV d’évaluation. AssessmentTimeZoneId enregistre le fuseau horaire utilisé pour interpréter la valeur sans ModifiedAt décalage.

Conservez les pages sans partie, les pages d’accueil, les pages de publication et les pages avec des mappages non résolus dans des files d’attente de révision distinctes. Les pages en dehors de la bibliothèque par défaut SitePages restent également sur le chemin d’accès à une seule page révisée séparément.

Comprendre les valeurs par défaut de préservation du code source

Attention

-TakeSourcePageName Renomme la page source classique et -Overwrite remplace une page cible existante. N’utilisez aucune des deux options tant que les pages générées n’ont pas été approuvées et qu’un plan de restauration n’a pas été mis en place.

Option Orientations pour la première vague
Attribution de noms par défaut Conservez le nom de la source et créez Migrated_<source-page>.aspx.
-TakeSourcePageName Ne pas utiliser initialement. Elle renomme la source classique avec un Previous_ préfixe.
-Overwrite Ne pas utiliser initialement. Examiner une cible existante au lieu de la remplacer automatiquement.
-ReplaceHomePageWithDefault Ne l’utilisez pas dans une vague représentative.
-DontPublish Utilisez pour la première vague afin que la page générée reste un brouillon lors de la validation.
-SkipItemLevelPermissionCopyToClientSidePage Utiliser avec l’application AllSites.Manage , sauf si des autorisations uniques doivent être copiées.

Annuler un brouillon de première vague

Le workflow de traitement par lots ne renomme ni ne remplace la page source classique. En cas d’échec de la validation d’un brouillon généré :

  1. Conservez la page source classique en service.
  2. Keep TransformationStatus=Created, set ValidationStatus=Failed, and fill ValidationNotes, ValidatedByet ValidatedAt.
  3. Conserver TargetPageUrl et LogPath avec les preuves de validation échouées.
  4. Recyclez le brouillon généré Migrated_ à partir de la bibliothèque Pages du site lorsqu’il n’est plus nécessaire pour l’investigation et que la stratégie de rétention de l’organisation permet la suppression.
  5. Corrigez la règle du candidat ou la correction, puis réessayez d’appliquer une page représentative avant de reprendre la vague.

-Overwrite et -TakeSourcePageName sont en dehors du flux de travail par lots. Avant d’utiliser l’une ou l’autre option dans une procédure distincte, conservez les versions de page et les URL, enregistrez le paramètre actuel de la page d’accueil, testez le processus de changement de nom ou de restauration inversé dans un site hors production et obtenez une approbation explicite.

Transformer une page Wiki ou WebPart sélectionnée

Utilisez le script de page représentative avec une ligne marquée .Selected=True Cela permet de conserver le test d’une page sur le même contrat de validation, d’authentification et de résultat qu’une vague plus importante.

Les scripts de commandes prennent en charge les pages Wiki et WebPart dans la bibliothèque par défaut SitePages . Excluent les pages d’accueil, les pages en aucune partie, les pages avec des autorisations uniques et les pages modifiées après évaluation. Traitez ces pages via un chemin d’accès examiné séparément.

Transformer toutes les pages représentatives

Enregistrez les trois fichiers intégrés de la référence de script d’onde de page dans le même dossier.

Dans representative-page-groups.csv:

  1. Défini IncludePattern=True pour chaque modèle de transformation dans la migration planifiée.
  2. Mis Selected=True sur au moins une page dans chaque modèle inclus.
  3. Remplissez ExpectedVisibleContent et ValidationOwner pour chaque page sélectionnée.

Affichez un aperçu de la vague complète sans authentifier ni écrire de pages SharePoint :

.\Convert-RepresentativePages.ps1 `
  -ManifestPath .\representative-page-groups.csv `
  -ClientId "<application-id>" `
  -AuthenticationMode Interactive `
  -WhatIf `
  -Force

La préversion des enregistrements PlannedAction CSV et PlannedTargetPageUrl. Parce que -WhatIf n’authentifie pas, TargetExists est NotChecked.

Exécutez un contrôle en lecture seule authentifié pour vérifier la source actuelle, la page d’accueil, les autorisations, les horodatages et l’absence de la cible :

.\Convert-RepresentativePages.ps1 `
  -ManifestPath .\representative-page-groups.csv `
  -ClientId "<application-id>" `
  -AuthenticationMode Interactive `
  -PreflightOnly `
  -Confirm:$false `
  -Force

Chaque ligne doit signaler TransformationStatus=PreflightPassed avant la conversion en direct.

Exécutez de manière interactive avec Confirmation à fort impact :

.\Convert-RepresentativePages.ps1 `
  -ManifestPath .\representative-page-groups.csv `
  -ClientId "<application-id>" `
  -AuthenticationMode Interactive `
  -Confirm

Le script écrit chaque résultat immédiatement dans representative-page-results.csv. Les pages générées restent des brouillons et chaque ligne créée commence par ValidationStatus=Pending.

Suivez Valider les pages classiques transformées. Définissez ValidationStatus=Passed, ValidationNotes, ValidatedBy, et ValidatedAt uniquement lorsque la page répond à tous les critères d’acceptation.

Développer sur toutes les pages spécifiées par l’utilisateur

Créez approved-pages.csv en copiant les lignes supplémentaires incluses que l’utilisateur a approuvées à partir de l’original representative-page-groups.csv. Conserver chaque champ généré, remplir ExpectedVisibleContent et ValidationOwner.

Exécutez le script de la page sélectionnée en premier -PreflightOnly -Confirm:$false -Force . Chaque ligne doit signaler PreflightPassed.

Exécutez le script d’extension :

.\Convert-SelectedPages.ps1 `
  -PagesPath .\approved-pages.csv `
  -RepresentativeManifestPath .\representative-page-groups.csv `
  -RepresentativeResultsPath .\representative-page-results.csv `
  -ClientId "<application-id>" `
  -AuthenticationMode Interactive `
  -Confirm

Le script refuse de s’étendre lorsque :

  • Le manifeste représentatif et les résultats ne correspondent pas.
  • Toute page représentative n’est pas Created et Passed.
  • Notes de validation, validateur ou horodatage de validation manquants.
  • La version PowerShell PnP ou l’un des trois fichiers de script diffère de l’exécution représentative.
  • Une page approuvée n’est pas une ligne incluse inchangée du manifeste d’origine.
  • Une page approuvée appartient à un modèle sans représentant passé.

La vague élargie crée également des pages de brouillon et écrit selected-page-results.csv. Validez ces pages avant de les publier.

Options nécessitant un examen explicite

Utilisez la référence de l’applet de commande ConvertTo-PnPPage générée pour le contrat de paramètres complet.

Les scripts de commandes ne prennent pas en charge les mappages de composants WebPart personnalisés, les pages de publication ou les cibles intersites. Gestion de ces scénarios à l’aide d’une seule page révisée séparément ou d’une procédure avancée.

Examinez ces options uniquement en dehors du flux de travail par lots :

  • -CopyPageMetadata et -KeepPageCreationModificationInformation.
  • -UrlMappingFile, -UserMappingFileet -TermMappingFile.
  • -Overwrite et -TakeSourcePageName après approbation et planification de restauration.

Résolution des problèmes liés à la page moderne

Les scripts d’onde de page n’activent pas les fonctionnalités SharePoint. Ce chemin de dépannage s’applique uniquement à un site d’équipe classique pris en charge. N’activez pas la fonctionnalité sur un portail de publication classique ; acheminez les pages de publication vers le backlog et le modèle de publication intersites distincts. Voir Personnalisations prises en charge pour les pages modernes.

Connectez-vous avec un compte autorisé à gérer le web, et listez les fonctionnalités web activées :

$source = Connect-PnPOnline `
  -Url "https://<tenant>.sharepoint.com/sites/<site>" `
  -Interactive `
  -ClientId "<application-id>" `
  -ReturnConnection

$modernPageFeatureId = [guid]'B6917CB1-93A0-4B97-A84D-7CF49975D4EC'
$modernPageFeature = Get-PnPFeature `
  -Scope Web `
  -Connection $source |
  Where-Object DefinitionId -eq $modernPageFeatureId

if ($modernPageFeature) {
  Write-Host "Modern pages feature is active."
}
else {
  Write-Host "Modern pages feature is not active."
}

L’application déléguée AllSites.Manage utilisée par les scripts de commandes par lots n’est pas suffisante pour activer les fonctionnalités web. Si la fonctionnalité n’est pas active sur un site d’équipe classique pris en charge, obtenez l’approbation du propriétaire du site et connectez-vous avec :

  • Une application déléguée distincte avec SharePoint AllSites.FullControl.
  • Un compte connecté avec un contrôle total sur le web.
$adminConnection = Connect-PnPOnline `
  -Url "https://<tenant>.sharepoint.com/sites/<site>" `
  -Interactive `
  -ClientId "<full-control-application-id>" `
  -ReturnConnection

Enable-PnPFeature `
  -Identity $modernPageFeatureId `
  -Scope Web `
  -Connection $adminConnection

Réexécutez le contrôle en amont authentifié après avoir activé la fonctionnalité.

Authentification sans assistance et autres types de pages

L’application cliente publique déléguée créée précédemment ne peut pas être réutilisée pour l’authentification de certificat application uniquement, sauf si elle est configurée séparément pour l’accès application uniquement.

Avant l’exécution sans assistance :

  1. Créez une inscription et un certificat distincts pour l’application en suivant Enregistrer une application d’ID Entra pour un accès à l’application uniquement.
  2. Configurez les autorisations d’application SharePoint ou les affectations de sites pour chaque site source en suivant Déterminer les autorisations PowerShell PnP requises.
  3. Accordez le consentement administrateur requis.
  4. Exécutez le script batch avec -PreflightOnly -Confirm:$false et le mode d’authentification par certificat.
  5. Supprimez -PreflightOnly uniquement une fois le contrôle en amont authentifié réussi dans un client test.

Importante

Les chemins d’accès aux paramètres de certificat sont testés par Pester, mais le locataire en direct de l’étape 2 exécute l’authentification interactive déléguée validée. Validez le profil d’autorisation d’application uniquement choisi dans votre locataire avant les écritures sans assistance.

Les pages de publication, les pages de blog, les pages externes SitePages, les pages d’accueil, les mappages de composants WebPart personnalisés et les sources SharePoint Server ne sont pas pris en charge par les scripts batch. Utilisez ces références avancées :

Étapes suivantes

  1. Validez chaque page transformée.
  2. Exécutez Convert-SelectedPages.ps1 uniquement une fois que chaque page représentative a réussi la validation.

Référence