Transformación de páginas clásicas seleccionadas con PowerShell PnP

La herramienta de evaluación de Microsoft 365 realiza inventarios de páginas clásicas, pero no las modifica. Use la salida Evaluación para aprobar una oleada de páginas y use PowerShell ConvertTo-PnPPage PnP para crear las páginas modernas.

Nota:

PnP PowerShell es una solución de código abierto con una comunidad activa que ofrece su soporte. No hay ningún contrato de nivel de servicio para el soporte de la herramienta de código abierto de Microsoft.

Flujo de trabajo de transformación de página

  1. Seleccione una oleada de página representativa de la cobertura de evaluación completada.
  2. Resuelva los elementos web de bloqueo y elija un destino local o entre sitios.
  3. Prepare una aplicación de PowerShell PnP propiedad del inquilino y los permisos necesarios.
  4. Transforme la onda representativa con valores predeterminados y registros que conservan el origen.
  5. Valide todas las páginas generadas antes de expandir la ola.

Antes de empezar

Complete estos requisitos previos:

  1. Ejecute e interprete la evaluación de páginas clásicas.
  2. Seleccione una ola representativa de la cobertura de examen correcta.
  3. Instale PowerShell 7.4.0 o posterior y la versión de PowerShell PnP estable actual.
  4. Registre una aplicación de Microsoft Entra propiedad del inquilino para PowerShell PnP interactivo.
  5. Confirme que el usuario que ha iniciado sesión puede editar páginas en las webs de origen y de destino.

Desde el 9 de septiembre de 2024, la autenticación interactiva de PowerShell PnP requiere su propio registro de aplicación y su identificador de cliente.

La cuenta que registra la aplicación debe tener permiso para crear registros de aplicaciones. La directiva de consentimiento del inquilino determina si un administrador debe conceder su consentimiento.

Permissions

Use una aplicación delegada independiente de la aplicación de evaluación de solo lectura.

Requisito de transformación Ámbito delegado de SharePoint
Leer el origen y crear, guardar y publicar la página moderna AllSites.Manage
Copie también los permisos únicos de nivel de elemento. AllSites.FullControl

También se aplican los permisos de sitio del usuario que ha iniciado sesión. El ámbito delegado de la aplicación no concede al usuario acceso a un sitio al que no pudo acceder de otro modo.

Con AllSites.Manage, agregue -SkipItemLevelPermissionCopyToClientSidePage para que la página generada herede permisos de su biblioteca. Use AllSites.FullControl solo cuando se deben conservar los permisos únicos de la página.

Consulte Migración de páginas clásicas con el menor permiso posible.

Instalación o actualización de PowerShell de PnP

PnP PowerShell requiere PowerShell 7.4.0 o posterior.

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

Si PnP PowerShell ya está instalado, ejecute Update-Module PnP.PowerShell desde PowerShell 7.4.0 o posterior.

Consulte Instalación de PowerShell PnP.

Registro de la aplicación de transformación interactiva

El comando siguiente crea una aplicación pública-cliente para el inicio de sesión interactivo:

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

Copie el identificador de aplicación devuelto. En función de la directiva de consentimiento del inquilino, es posible que un administrador tenga que conceder el consentimiento antes de la primera conexión.

Este registro de cliente público es para el inicio de sesión de dispositivo o interactivo delegado. No proporciona los permisos de aplicación ni el certificado necesarios para la autenticación desatendida.

Para ver el registro manual y otros métodos de autenticación, consulte Registro de una aplicación de identificador de Entra para PowerShell PnP.

Para GCC High, DoD o Microsoft 365 operado por 21Vianet, especifique el valor coincidente -AzureEnvironment al registrar la aplicación y conectarse. Consulte las referencias de cmdlet Register-PnPEntraIDAppForInteractiveLogin y Connect-PnPOnline .

Asignación de una fila de evaluación a PowerShell de PnP

Campo de evaluación Uso de PowerShell de PnP
SiteUrl + WebUrl Dirección URL de origen para Connect-PnPOnline.
ListUrl, ListId, PageUrl Biblioteca exacta SitePages e identidad de archivo de origen.
PageType Debe ser WikiPage o WebPartPage para este flujo de trabajo.
Layout Agrupación y validación de patrones representativos.

Antes de transformar una página de primera onda, necesita:

  • Cobertura de sitio y web correcta.
  • PageType es igual a WikiPage o WebPartPage.
  • No hay elementos web sin asignar sin resolver.
  • WebPartCount mayor que 0. Controle páginas de cero partes fuera de este ejemplo automatizado después de la revisión manual.
  • Página de origen que hereda permisos de su biblioteca.
  • Una línea base de diseño y contenido grabados para la validación.

Creación de grupos de páginas representativos

El siguiente script crea un inventario de candidatos. No transforma páginas.

Agrupa las páginas wiki y elementos web aptas por tipo de página, diseño y firma de elemento web ordenada. La firma incluye el tipo de elemento web, el resultado de la asignación, el estado oculto y el estado cerrado.

$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

Revise representative-page-groups.csv y seleccione al menos una página de cada una de las PatternKey que contendrá la ola de migración. Seleccione páginas adicionales cuando las propiedades del elemento web, el contenido vinculado o el comportamiento empresarial difiera materialmente dentro de un patrón.

Establecer IncludePattern=False para patrones fuera de la migración planeada. Para cada página seleccionada, establezca Selected=True y rellene ExpectedVisibleContent y ValidationOwner.

Ejecute el paso de agrupación en el mismo equipo que generó los CSP de evaluación. AssessmentTimeZoneId registra la zona horaria utilizada para interpretar el valor sin ModifiedAt desplazamiento.

Mantenga páginas de cero partes, páginas principales, páginas de publicación y páginas con asignaciones sin resolver en colas de revisión independientes. Las páginas fuera de la biblioteca predeterminada SitePages también permanecen en la ruta de acceso de página única revisada por separado.

Descripción de los valores predeterminados que conservan el origen

Precaución

-TakeSourcePageName cambia el nombre de la página de origen clásica y -Overwrite reemplaza una página de destino existente. No use ninguna de las opciones hasta que se aprueben las páginas generadas y exista un plan de reversión.

Opción Guía de primera onda
Nomenclatura predeterminada Mantenga el nombre de origen y cree Migrated_<source-page>.aspx.
-TakeSourcePageName No lo use inicialmente. Cambia el nombre del origen clásico con un Previous_ prefijo.
-Overwrite No lo use inicialmente. Revise un destino existente en lugar de reemplazarlo automáticamente.
-ReplaceHomePageWithDefault No lo use en una ola representativa.
-DontPublish Use para la primera oleada para que la página generada siga siendo un borrador durante la validación.
-SkipItemLevelPermissionCopyToClientSidePage Use con la AllSites.Manage aplicación a menos que se deban copiar permisos únicos.

Revertir un borrador de primera oleada

El flujo de trabajo por lotes no cambia el nombre ni sobrescribe la página de origen clásica. Si se produce un error en la validación de un borrador generado:

  1. Mantenga la página de origen clásica en servicio.
  2. Mantenga TransformationStatus=Created, establezca ValidationStatus=Failedy rellene ValidationNotes, ValidatedByy ValidatedAt.
  3. Conservar TargetPageUrl y LogPath con la evidencia de validación errónea.
  4. Recicle el borrador generado Migrated_ de la biblioteca de páginas del sitio cuando ya no sea necesario para la investigación y la directiva de retención de la organización permita la eliminación.
  5. Corrija la regla o corrección candidata y vuelva a intentar una página representativa antes de reanudar la ola.

-Overwrite y -TakeSourcePageName están fuera del flujo de trabajo por lotes. Antes de usar cualquiera de las opciones en un procedimiento independiente, conserve las versiones de página y las direcciones URL, registre la configuración actual de la página principal, pruebe el proceso de cambio de nombre o restauración inverso en un sitio que no sea de producción y obtenga aprobación explícita.

Transformar una página wiki o elemento web seleccionada

Use el script de página representativa con una fila marcada como Selected=True. Esto mantiene la prueba de una página en el mismo contrato de validación, autenticación y resultado que una oleada mayor.

Los scripts por lotes admiten páginas wiki y elementos web en la biblioteca predeterminada SitePages . Excluyen las páginas principales, las páginas de cero partes, las páginas con permisos únicos y las páginas modificadas después de la evaluación. Controlar esas páginas a través de una ruta de acceso revisada por separado.

Transformar todas las páginas representativas

Guarde los tres archivos incrustados de la referencia de script de onda de página en la misma carpeta.

En representative-page-groups.csv:

  1. Establezca IncludePattern=True para cada patrón de transformación en la migración planeada.
  2. Establezca Selected=True en al menos una página en cada patrón incluido.
  3. Rellene ExpectedVisibleContent y ValidationOwner para cada página seleccionada.

Obtenga una vista previa de la oleada completa sin autenticar ni escribir páginas de SharePoint:

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

Los registros PlannedAction CSV de vista previa y PlannedTargetPageUrl. Dado -WhatIf que no se autentica, TargetExists es NotChecked.

Ejecute una comprobación preliminar de solo lectura autenticada para comprobar el origen actual, la página principal, los permisos, las marcas de tiempo y la ausencia de destino:

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

Cada fila debe informar TransformationStatus=PreflightPassed antes de la conversión en vivo.

Ejecute interactivamente con confirmación de alto impacto:

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

El script escribe cada resultado inmediatamente en representative-page-results.csv. Las páginas generadas siguen siendo borradores y cada fila creada comienza por ValidationStatus=Pending.

Siga Validar páginas clásicas transformadas. Establezca ValidationStatus=Passed, ValidationNotes, ValidatedByy ValidatedAt solo después de que la página cumpla todos los criterios de aceptación.

Expandir a todas las páginas especificadas por el usuario

Cree approved-pages.csv copiando las filas incluidas adicionales que el usuario aprobó del original representative-page-groups.csv. Conserve todos los campos generados y rellene ExpectedVisibleContent y ValidationOwner.

Ejecute primero el script -PreflightOnly -Confirm:$false -Force de página seleccionado. Cada fila debe informar de PreflightPassed.

Ejecute el script de expansión:

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

El script se niega a expandirse cuando:

  • El manifiesto representativo y los resultados no coinciden.
  • Cualquier página representativa no Created es y Passed.
  • Faltan notas de validación, validador o marca de tiempo de validación.
  • La versión de PowerShell de PnP o cualquiera de los tres archivos de script difiere de la ejecución representativa.
  • Una página aprobada no es una fila incluida sin cambios del manifiesto original.
  • Una página aprobada pertenece a un patrón sin un representante pasado.

La oleada expandida también crea borradores selected-page-results.csvde páginas y escribe . Valide esas páginas antes de publicarlas.

Opciones que requieren revisión explícita

Use la referencia de cmdlet ConvertTo-PnPPage generada para el contrato de parámetros completo.

Los scripts por lotes no admiten asignaciones de elementos web personalizados, páginas de publicación ni destinos entre sitios. Controlar esos escenarios a través de un procedimiento avanzado o de página única revisados por separado.

Revise estas opciones solo fuera del flujo de trabajo por lotes:

  • -CopyPageMetadata y -KeepPageCreationModificationInformation.
  • -UrlMappingFile, -UserMappingFiley -TermMappingFile.
  • -Overwrite y -TakeSourcePageName después de la aprobación y reversión del planeamiento.

Solución de problemas de la funcionalidad de página moderna

Los scripts de onda de página no habilitan las características de SharePoint. Esta ruta de solución de problemas solo se aplica a un sitio de equipo clásico compatible. No habilite la característica en un portal de publicación clásico; enrutar las páginas de publicación al modelo y trabajo pendiente de publicación entre sitios independientes. Consulte Personalizaciones admitidas para páginas modernas.

Conéctese con una cuenta autorizada para administrar la web y enumere las características web activadas:

$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."
}

La aplicación delegada AllSites.Manage usada por los scripts por lotes no es suficiente para activar las características web. Si la característica no está activa en un sitio de equipo clásico compatible, obtenga la aprobación del propietario del sitio y conéctese con:

  • Una aplicación delegada independiente con SharePoint AllSites.FullControl.
  • Una cuenta con inicio de sesión con control total en la 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

Vuelva a ejecutar la versión preliminar autenticada después de habilitar la característica.

Autenticación desatendida y otros tipos de página

La aplicación cliente pública delegada creada anteriormente no se puede reutilizar para la autenticación de solo aplicación de certificado a menos que esté configurada por separado para el acceso solo a la aplicación.

Antes de la ejecución desatendida:

  1. Cree un certificado y un registro de solo aplicación independientes siguiendo Registro de una aplicación de identificador de Entra para el acceso solo a la aplicación.
  2. Configure los permisos de aplicación de SharePoint o las asignaciones de sitio para cada sitio de origen siguiendo la sección Determinación de los permisos de PowerShell PnP necesarios.
  3. Conceda el consentimiento del administrador necesario.
  4. Ejecute el script por lotes con -PreflightOnly -Confirm:$false y el modo de autenticación de certificados.
  5. Quite -PreflightOnly solo después de que la comprobación preliminar autenticada pase en un inquilino de prueba.

Importante

Las rutas de acceso de parámetros de certificado se prueban con Pester, pero el inquilino activo de la fase 2 ejecuta la autenticación interactiva delegada validada. Valide el perfil de permiso de solo aplicación elegido en el inquilino antes de las escrituras desatendidas.

Las páginas de publicación, las páginas de blog, las páginas fuera SitePagesde , las páginas principales, las asignaciones de elementos web personalizados y los orígenes de SharePoint Server no son compatibles con los scripts por lotes. Use estas referencias avanzadas:

Pasos siguientes

  1. Valide cada página transformada.
  2. Ejecute Convert-SelectedPages.ps1 solo después de que cada página representativa pase la validación.

Referencia