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 d’é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.

Flux de travail 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 intersites.
  3. Préparez une application PowerShell PnP appartenant au locataire et les autorisations requises.
  4. Transformez la vague représentative avec les valeurs par défaut de conservation de la source et la journalisation.
  5. Validez chaque page générée avant de développer la vague.

Avant de commencer

Remplissez les conditions préalables suivantes :

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

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

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

Autorisations

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

Condition requise pour la transformation Étendue SharePoint déléguée
Lire la source et créer, enregistrer et publier la page moderne AllSites.Manage
Copiez é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 afin que la page générée hérite des autorisations de sa bibliothèque. Utilisez AllSites.FullControl uniquement lorsque les autorisations uniques de la page doivent être conservées.

Consultez Migrer des pages classiques avec le moins d’autorisations possible.

Installer ou mettre à jour PnP PowerShell

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

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

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

Consultez Installer PnP PowerShell.

Inscrire l’application de transformation interactive

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

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

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

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

Pour obtenir une inscription manuelle et d’autres méthodes d’authentification, consultez Inscrire une application d’ID Entra pour PnP PowerShell.

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 à PnP PowerShell

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

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

  • Couverture du site et du web réussies.
  • PageType égal à WikiPage ou WebPartPage.
  • Aucun composant WebPart non mappé non résolu.
  • WebPartCount supérieur à 0. Gérez les pages en partie zéro 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 à des fins de validation.

Créer des groupes de pages représentatifs

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

Il regroupe les pages wiki et de composants WebPart éligibles par type de page, mise en page et signature de composant WebPart ordonné. La signature inclut 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 dans chacune PatternKey des pages que la vague de migration contiendra. 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éfini IncludePattern=False pour les modèles en dehors de la migration planifiée. Pour chaque page sélectionnée, définissez Selected=True et remplissez 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 situées en dehors de la bibliothèque par défaut SitePages restent également sur le chemin d’accès monopage révisé séparément.

Comprendre les valeurs par défaut de préservation de la source

Attention

-TakeSourcePageName renomme la page source classique et -Overwrite remplace une page cible existante. N’utilisez pas l’une ou l’autre option tant que les pages générées n’ont pas été approuvées et qu’un plan de restauration n’existe pas.

Option Guide de la première vague
Nommage par défaut Conservez le nom de la source et créez Migrated_<source-page>.aspx.
-TakeSourcePageName N’utilisez pas au départ. Il renomme la source classique avec un Previous_ préfixe.
-Overwrite N’utilisez pas au départ. Passez en revue une cible existante au lieu de la remplacer automatiquement.
-ReplaceHomePageWithDefault N’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 pendant la validation.
-SkipItemLevelPermissionCopyToClientSidePage Utilisez avec l’application AllSites.Manage , sauf si des autorisations uniques doivent être copiées.

Restaurer un brouillon de première vague

Le workflow de traitement par lots ne renomme pas ou ne remplace pas la page source classique. Si la validation d’un brouillon généré échoue :

  1. Conservez la page source classique en service.
  2. Conservez TransformationStatus=Created, définissez ValidationStatus=Failedet remplissez ValidationNotes, ValidatedByet ValidatedAt.
  3. Conservez TargetPageUrl et LogPath avec la preuve de validation ayant échoué.
  4. Recyclez le brouillon généré Migrated_ à partir de la bibliothèque pages de site lorsqu’il n’est plus nécessaire pour l’examen et que la stratégie de rétention du organization autorise la suppression.
  5. Corrigez la règle ou la correction candidate, puis réessayez une page représentative avant de reprendre la vague.

-Overwrite et -TakeSourcePageName se trouvent en dehors du workflow de traitement par lots. Avant d’utiliser l’une ou l’autre option dans une procédure distincte, conservez les versions et URL des pages, enregistrez le paramètre de page d’accueil actuel, testez le processus de changement de nom ou de restauration dans un site de non-production et obtenez une approbation explicite.

Transformer une page wiki ou de composant WebPart sélectionnée

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

Les scripts de traitement par lots prennent en charge les pages wiki et de composants WebPart dans la bibliothèque par défaut SitePages . Ils excluent les pages d’accueil, les pages en partie nulle, les pages avec des autorisations uniques et les pages modifiées après l’évaluation. Gérez ces pages via un chemin d’accès révisé séparément.

Transformer toutes les pages représentatives

Enregistrez les trois fichiers incorporés à partir de la référence de script Page wave 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. Défini 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 ou écrire des pages SharePoint :

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

Les enregistrements PlannedAction CSV en préversion et PlannedTargetPageUrl. Étant donné que -WhatIf ne s’authentifie pas, TargetExists est NotChecked.

Exécutez un contrôle préliminaire en lecture seule authentifié pour vérifier la source, 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 dynamique.

Exécutez de manière interactive avec une 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, ValidatedByet ValidatedAt uniquement une fois que la page répond à chaque critère d’acceptation.

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

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

Exécutez d’abord le script de page sélectionnée.-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 développer dans les cas suivants :

  • Le manifeste et les résultats représentatifs ne correspondent pas.
  • Toute page représentative n’est pas Created et Passed.
  • Les notes de validation, le validateur ou l’horodatage de validation sont manquants.
  • La version de PnP PowerShell 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é.

L’onde développée crée également des brouillons de pages et écrit selected-page-results.csv. Validez ces pages avant de les publier.

Options nécessitant une révision explicite

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

Les scripts batch ne prennent pas en charge les mappages de composants WebPart personnalisés, les pages de publication ou les cibles intersites. Gérez ces scénarios par le biais d’une procédure monopage ou avancée examinée séparément.

Passez en revue ces options uniquement en dehors du workflow de traitement par lots :

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

Résoudre les problèmes liés aux fonctionnalités de page modernes

Les scripts d’onde de page n’activent pas les fonctionnalités SharePoint. Ce chemin de résolution des problèmes 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. Consultez Personnalisations prises en charge pour les pages modernes.

Connectez-vous avec un compte autorisé à gérer le web et répertoriez 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 traitement 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 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 la préversion authentifiée 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 d’application de certificat uniquement, sauf si elle est configurée séparément pour l’accès à l’application uniquement.

Avant l’exécution sans assistance :

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

Importante

Les chemins d’accès aux paramètres de certificat sont testés par Pester, mais le locataire actif 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 en dehors SitePagesde , 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 de traitement par lots. Utilisez ces références avancées :

Étapes suivantes

  1. Valider 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