Migrar SharePoint 2016 y 2019 a Subscription Edition: los scripts
SharePoint 2016 va directo a Subscription Edition. No hay salto por 2019, el método es database attach y ninguno más, y el orden de las service applications no es una preferencia. La secuencia completa en PowerShell, desde el inventario que se toma antes de tocar nada hasta el rastreo que se lanza al final.
El soporte de SharePoint Server 2016 y 2019 termina el 14 de julio de 2026, y el único destino on-premises soportado es Subscription Edition. Este artículo es la secuencia, en PowerShell, con las partes que bloquean una migración señaladas donde muerden de verdad.
Una cosa antes del código, porque cambia el plan y el presupuesto.
SharePoint 2016 va directo a Subscription Edition
La creencia más cara de este proyecto es que hay que pasar primero por 2019. No hay que hacerlo.
"SharePoint Server Subscription Edition admite actualización de versión a versión N - 1 y N - 2. Puede actualizar directamente desde los siguientes productos de SharePoint usando el procedimiento estándar de database attach: SharePoint Server 2019 (incluido Project Server 2019), SharePoint Server 2016 (incluido Project Server 2016)."
Un salto, desde cualquiera de los dos. El salto doble solo es obligatorio por debajo de 2016:
"No se admite actualizar directamente mediante database attach desde versiones de SharePoint anteriores a SharePoint Server 2016. SharePoint 2013, SharePoint 2010 y sucesivos deben actualizarse primero a SharePoint Server 2016 o SharePoint Server 2019 mediante database attach, antes de actualizar a SharePoint Server Subscription Edition."

Y hay un suelo debajo de todo esto:
"Todas las bases de datos deben estar actualizadas a la versión 16.0.4351.1000 o superior; de lo contrario, la actualización a SharePoint Server Subscription Edition quedará bloqueada."
Ese número es la build RTM de SharePoint Server 2016. Una base de datos nacida en 2016 lo supera por definición. La que se rechaza es la que vino de 2013, se adjuntó a una granja 2016 y nunca llegó a terminar el viaje.
El método decide el plan
No hay actualización in situ. La única vía soportada es database attach, es decir, se construye una segunda granja y se mueve contenido a ella. La configuración no viaja: web applications, service applications, políticas y ajustes se reconstruyen a mano en la granja nueva. Eso no es una limitación que sortear, es la forma del proyecto.

Todo lo que sigue asume la SharePoint Management Shell abierta como administrador elevado, con la cuenta teniendo db_owner en cada base de datos que se actualiza, securityadmin en la instancia SQL, pertenencia al grupo de Administradores local, y los derechos concedidos mediante Add-SPShellAdmin.
Ninguno de los scripts de abajo se ejecutó contra una granja. No tenemos ninguna. Cada cmdlet y cada parámetro viene de la documentación de Microsoft, pero la secuencia completa no se ha ejecutado, así que trátela como un plan que ensayar y no como un script para pegar en producción. La sección del ensayo, al final, no es un consejo opcional.
Fase 0: el inventario, tomado antes de que nada se mueva
La granja nueva tiene que poder responder por todo lo que tenía la vieja. Tome el inventario primero, guárdelo en el control de versiones, y compárelo al final. Esto se ejecuta en la granja vieja.
# INVENTORY.PS1: runs on the SharePoint 2016 or 2019 farm.
# Reads only. Produces the record that the new farm gets compared against.
$out = "C:\Migration\inventory"
New-Item -ItemType Directory -Path $out -Force | Out-Null
# Patch level of every SharePoint product in the farm. This is the documented
# way to see what is actually installed, server by server.
Get-SPProduct |
Select-Object ProductName, @{n='Patches';e={ $_.PatchableUnitDisplayNames -join '; ' }} |
Export-Csv "$out\products.csv" -NoTypeInformation -Encoding UTF8
# Web applications with their URLs and authentication. The new farm has to
# reproduce these URLs exactly, or every link inside the content breaks.
Get-SPWebApplication -IncludeCentralAdministration |
Select-Object DisplayName, Url,
@{n='Zones';e={ ($_.AlternateUrls | ForEach-Object { "$($_.UrlZone)=$($_.IncomingUrl)" }) -join ' | ' }},
@{n='ClaimsMode';e={ $_.UseClaimsAuthentication }} |
Export-Csv "$out\webapps.csv" -NoTypeInformation -Encoding UTF8
# Content databases, their sizes and how many site collections each holds.
# The counts are what tells you which mount will take twenty minutes and
# which will take six hours.
Get-SPContentDatabase |
Select-Object Name, Server, WebApplication, CurrentSiteCount,
@{n='SizeGB';e={ [math]::Round($_.DiskSizeRequired / 1GB, 2) }} |
Export-Csv "$out\contentdbs.csv" -NoTypeInformation -Encoding UTF8
# Farm solutions. These have to be deployed to the new farm BEFORE the content
# databases are tested, and this list is what you deploy.
Get-SPSolution |
Select-Object Name, Deployed, ContainsGlobalAssembly, ContainsWebApplicationResource,
@{n='DeployedTo';e={ ($_.DeployedWebApplications | ForEach-Object { $_.Url }) -join ' | ' }} |
Export-Csv "$out\solutions.csv" -NoTypeInformation -Encoding UTF8
# Service applications and their databases. Five of these can be upgraded.
# Everything else on this list is a rebuild, and it is better to know now.
Get-SPServiceApplication |
Select-Object DisplayName, TypeName, Status |
Export-Csv "$out\serviceapps.csv" -NoTypeInformation -Encoding UTF8
Get-SPDatabase |
Select-Object Name, Type, Server,
@{n='SizeGB';e={ [math]::Round($_.DiskSizeRequired / 1GB, 2) }} |
Export-Csv "$out\databases.csv" -NoTypeInformation -Encoding UTF8
# Every site collection, with its template. The templates are what a missing
# feature shows up as later, so this is the list you check against.
Get-SPSite -Limit All |
Select-Object Url, @{n='Template';e={ $_.RootWeb.WebTemplate + '#' + $_.RootWeb.Configuration }},
ContentDatabase, Owner |
Export-Csv "$out\sites.csv" -NoTypeInformation -Encoding UTF8
Write-Host "Inventory written to $out" -ForegroundColor Green
Dos de esos ficheros se ganan el sitio de inmediato. solutions.csv se convierte en la fase 2, y webapps.csv en la fase 1, porque las URL de la granja nueva tienen que coincidir con las viejas carácter a carácter.
Fase 1: la granja que lo recibe
Construya la granja de Subscription Edition y recree después las web applications. Una decisión que tomar a propósito: si piensa actualizar las bases de datos de las service applications, no use el Farm Configuration Wizard para crearlas. El asistente las crea vacías, y una service application de Managed Metadata vacía no es algo que luego pueda apuntar a su base de datos antigua.
Certificados primero, porque Subscription Edition los gestiona dentro de la granja y una web application puede recibir uno ya al crearse.
# CERTIFICATES. Subscription Edition deploys imported certificates to the
# Windows certificate store on every server in the farm automatically, and
# to any server that joins later.
$pfxPassword = Read-Host -AsSecureString -Prompt 'PFX password'
Import-SPCertificate -Path '\\fileserver\certs\sharepoint.contoso.com.pfx' `
-Password $pfxPassword -Exportable
# The whole chain has to be present, not just the leaf, or SSL connections fail.
Import-SPCertificate -Path '\\fileserver\certs\issuing-ca.p7b'
# Confirm what landed, and in which store.
Get-SPCertificate | Select-Object DisplayName, Store, NotAfter, Thumbprint
# Warn earlier than the default. The health rules then chase expiry for you.
Set-SPCertificateSettings -CertificateExpirationWarningThreshold 45
Después las web applications, coincidiendo con el inventario.
# WEB APPLICATIONS. The URL must match the old farm exactly: it is written
# into links, into search results and into anything anyone ever bookmarked.
$appPoolAccount = Get-SPManagedAccount 'CONTOSO\svc-sp-content'
# Windows claims. Classic mode was REMOVED for content web applications in
# Subscription Edition, so a farm that was still classic changes here, not later.
$ap = New-SPAuthenticationProvider
New-SPWebApplication -Name 'Contoso Intranet' `
-ApplicationPool 'ContosoIntranetPool' `
-ApplicationPoolAccount $appPoolAccount `
-AuthenticationProvider $ap `
-Port 443 -SecureSocketsLayer `
-HostHeader 'sharepoint.contoso.com' `
-Url 'https://sharepoint.contoso.com' `
-Certificate 'sharepoint.contoso.com' `
-UseServerNameIndication `
-DatabaseName 'SP_Content_Placeholder'
# Server Name Indication is what lets several web applications share port 443
# with their own certificates. Without it they all share one certificate.
La base de datos de relleno es deliberada: la web application necesita una para existir, y las de contenido reales llegan en la fase 4. Bórrela después, cuando las reales estén montadas.
Una trampa que cuesta una caída de servicio. Si más adelante cambia bindings con Set-SPWebApplication, indíquelos todos de nuevo:
"Todos los ajustes de binding de IIS deben volver a especificarse al actualizar el binding de un sitio IIS mediante el cmdlet
Set-SPWebApplication. Esto incluye la URL, el ajuste de secure sockets layer, el número de puerto, el host header y el certificado. Si un ajuste de binding no se vuelve a especificar, revertirá a su valor predeterminado."
# Right: every binding setting stated, even the ones that are not changing.
Set-SPWebApplication -Identity 'https://sharepoint.contoso.com' -Zone Default `
-Port 443 -SecureSocketsLayer `
-HostHeader 'sharepoint.contoso.com' `
-Url 'https://sharepoint.contoso.com' `
-Certificate 'sharepoint.contoso.com' `
-UseServerNameIndication
Fase 2: las personalizaciones van antes que el contenido
Este es el error de orden que produce la sesión de diagnóstico más larga y menos útil del proyecto. Test-SPContentDatabase reporta cada feature, plantilla y ensamblado que el contenido referencia y no encuentra. Ejecútelo antes de desplegar las soluciones y obtendrá un informe con cientos de entradas que son todas el mismo problema.
Microsoft lo señala como la causa común:
"Una causa frecuente de fallos durante la actualización es que al entorno le falten features, soluciones u otros elementos personalizados."
# SOLUTIONS. Driven from solutions.csv, produced by the inventory.
$wsps = Import-Csv 'C:\Migration\inventory\solutions.csv'
foreach ($w in $wsps) {
$path = Join-Path 'C:\Migration\wsp' $w.Name
if (-not (Test-Path $path)) {
Write-Warning "MISSING: $($w.Name). Find the package, or the sites that use it will not upgrade cleanly"
continue
}
$solution = Add-SPSolution -LiteralPath $path
# GACDeployment is required when the package contains a global assembly.
# The inventory recorded that per solution, so it is not a guess.
$gac = [bool]::Parse($w.ContainsGlobalAssembly)
if ($w.ContainsWebApplicationResource -eq 'True') {
Install-SPSolution -Identity $solution -AllWebApplications `
-GACDeployment:$gac -Force
} else {
Install-SPSolution -Identity $solution -GACDeployment:$gac -Force
}
}
# Deployment is asynchronous: it runs on a timer job. Wait for it, or the
# next phase tests against a farm that is still deploying.
do {
Start-Sleep -Seconds 15
$pending = Get-SPSolution | Where-Object { $_.JobExists }
Write-Host "Waiting for $($pending.Count) solution job(s)..."
} while ($pending)
Get-SPSolution | Select-Object Name, Deployed, DeploymentState | Format-Table -AutoSize
Lo que quede en la lista de los que faltan es una decisión, no un aviso. O se encuentra el paquete y se reconstruye, o los sitios que dependen de él se inventarían y se tratan antes de la migración, no durante.
Fase 3: congelar, copiar, descongelar
La granja vieja queda en solo lectura en vez de apagarse, para que la gente siga leyendo mientras corre la copia. Esto es T-SQL, en la instancia de origen.
-- ON THE OLD FARM'S SQL INSTANCE.
-- Read-only, not offline: people keep reading during the copy window.
ALTER DATABASE [WSS_Content_Intranet] SET READ_ONLY WITH ROLLBACK IMMEDIATE;
-- COPY_ONLY leaves the existing backup chain intact. Without it, this backup
-- becomes part of the chain and the scheduled restore plan quietly changes.
-- CHECKSUM makes the restore refuse a backup that was damaged in transit.
BACKUP DATABASE [WSS_Content_Intranet]
TO DISK = N'\\fileserver\migration\WSS_Content_Intranet.bak'
WITH COPY_ONLY, COMPRESSION, CHECKSUM, STATS = 5;
-- ON THE SUBSCRIPTION EDITION FARM'S SQL INSTANCE.
RESTORE DATABASE [WSS_Content_Intranet]
FROM DISK = N'\\fileserver\migration\WSS_Content_Intranet.bak'
WITH MOVE 'WSS_Content_Intranet' TO N'E:\SQLData\WSS_Content_Intranet.mdf',
MOVE 'WSS_Content_Intranet_log' TO N'F:\SQLLogs\WSS_Content_Intranet_log.ldf',
REPLACE, STATS = 5;
-- A restored copy inherits the read-only state, and a read-only database
-- cannot be attached. This is the step people forget, and Mount fails on it.
ALTER DATABASE [WSS_Content_Intranet] SET READ_WRITE WITH ROLLBACK IMMEDIATE;
Las mismas tres instrucciones se aplican a las bases de datos de las service applications, con una excepción que se trata en la fase siguiente: la base de administración de Search se copia más tarde, y solo después de haber pausado Search.
Fase 4: las service applications, en el orden que no es una preferencia
Cinco bases de datos de service applications pueden actualizarse: Business Data Connectivity, Managed Metadata, Secure Store, User Profile y Search. Todo lo demás se reconfigura a mano, y dos se rechazan explícitamente:
"Word Automation Services y Machine Translation Services no pueden actualizarse. Habrá que crear una nueva instancia del servicio."
El orden lo fijan las dependencias. Managed Metadata y User Profile van ambos antes que Search, y ambos antes de cualquier My Site.
# SERVICE APPLICATIONS. Order matters: MMS and UPA before Search.
$applicationPool = Get-SPServiceApplicationPool -Identity 'SharePoint Web Services default'
# --- Secure Store -------------------------------------------------------
# The passphrase is from the OLD farm. Without it the stored credentials are
# unreadable, and no amount of restoring gets them back.
$sss = New-SPSecureStoreServiceApplication -Name 'Secure Store' `
-ApplicationPool $applicationPool `
-DatabaseName 'Secure_Store_Service_DB' -AuditingEnabled
$sssp = New-SPSecureStoreServiceApplicationProxy -Name 'Secure Store Proxy' `
-ServiceApplication $sss -DefaultProxyGroup
$oldPassphrase = Read-Host -Prompt 'Secure Store passphrase from the old farm'
Update-SPSecureStoreApplicationServerKey -Passphrase $oldPassphrase `
-ServiceApplicationProxy $sssp
# --- Business Data Connectivity ----------------------------------------
# The only one that creates its own proxy and puts it in the default group.
New-SPBusinessDataCatalogServiceApplication -Name 'BDC Service' `
-ApplicationPool $applicationPool -DatabaseName 'BDC_Service_DB'
# --- Managed Metadata ---------------------------------------------------
$mms = New-SPMetadataServiceApplication -Name 'Managed Metadata Service' `
-ApplicationPool $applicationPool `
-DatabaseName 'Managed_Metadata_Service_DB'
New-SPMetadataServiceApplicationProxy -Name 'Managed Metadata Proxy' `
-ServiceApplication $mms -DefaultProxyGroup
# --- User Profile -------------------------------------------------------
# After Managed Metadata, and before any My Site is touched. The Sync
# database is NEW: only Profile and Social come across.
New-SPProfileServiceApplication -Name 'User Profile Service Application' `
-ApplicationPool $applicationPool `
-ProfileDBName 'UPA_ProfileDB' `
-SocialDBName 'UPA_SocialDB' `
-ProfileSyncDBName 'UPA_SyncDB'
$upa = Get-SPServiceApplication | Where-Object { $_.TypeName -eq 'User Profile Service Application' }
New-SPProfileServiceApplicationProxy -Name 'User Profile Proxy' -ServiceApplication $upa
$upaProxy = Get-SPServiceApplicationProxy |
Where-Object { $_.TypeName -eq 'User Profile Service Application Proxy' }
Add-SPServiceApplicationProxyGroupMember -member $upaProxy -identity ''
Search va el último, y tiene un paso que se ejecuta en la granja vieja a mitad de camino.
# --- Search, part one: ON THE OLD FARM ---------------------------------
# The Search Administration database is copied later than the others, because
# Search has to be paused first. While it is paused the old index stops
# updating, so results on the old farm get staler during the window.
$ssaOld = Get-SPEnterpriseSearchServiceApplication 'Search Service Application'
Suspend-SPEnterpriseSearchServiceApplication -Identity $ssaOld
# Now set the Search Admin DB read-only, back it up and restore it, as in phase 3.
# --- Search, part two: ON THE SUBSCRIPTION EDITION FARM ----------------
# The Search service instance cannot be started from Central Administration
# until a Search service application exists, so PowerShell it is.
$searchInst = Get-SPEnterpriseSearchServiceInstance -local
Start-SPServiceInstance $searchInst
# Restore, not New: this is what upgrades the admin database instead of
# creating an empty one. It keeps the search schema, the result sources and
# the query rules. It does NOT keep the index.
Restore-SPEnterpriseSearchServiceApplication `
-Name 'Search Service Application' `
-applicationpool $applicationPool `
-databasename 'Search_Service_Application_DB' `
-databaseserver 'SQLSE01' `
-AdminSearchServiceInstance $searchInst
$ssa = Get-SPEnterpriseSearchServiceApplication
New-SPEnterpriseSearchServiceApplicationProxy -Name 'Search Proxy' -SearchApplication $ssa
$ssap = Get-SPEnterpriseSearchServiceApplicationProxy
Add-SPServiceApplicationProxyGroupMember -member $ssap -identity ''
Si ese restore falla, y la latencia de red o de SQL basta para hacerlo fallar, la recuperación documentada no es reintentar encima: borrar la base de administración de Search a medio actualizar, restaurar de nuevo la copia de seguridad, ponerla en lectura y escritura, y ejecutar el comando otra vez.
Confirme después que todos los proxies quedaron en el grupo predeterminado, porque una service application que funciona pero cuyo proxy no está en el grupo predeterminado se comporta exactamente como una que falta.
$pg = Get-SPServiceApplicationProxyGroup -Identity ''
$pg.Proxies | Select-Object DisplayName, TypeName | Format-Table -AutoSize
Fase 5: probar, y solo después montar
Nunca monte primero. Test-SPContentDatabase no cambia nada, y es lo único que le dice qué falta mientras todavía es barato arreglarlo.
Dos parámetros se ganan el sitio. -ShowLocation dice dónde se está usando una feature que falta, lo que convierte un GUID en un sitio que tiene dueño. Es lento, así que pertenece al ensayo y no a la ejecución real. Y -ExtendedCheck:
"Comprueba si hay modos de autenticación inconsistentes durante el proceso de actualización por database attach. El modo elegido, claims o clásico, debe ser el mismo en ambas versiones."
Ese importa más de lo que parece, porque el modo clásico se eliminó para web applications de contenido en Subscription Edition. Una granja que todavía usa autenticación clásica se entera aquí, o se entera a mitad de un mount.
# TEST THEN MOUNT. Driven from the inventory, one database at a time.
$dbs = Import-Csv 'C:\Migration\inventory\contentdbs.csv'
$webApp = 'https://sharepoint.contoso.com'
$report = 'C:\Migration\reports'
New-Item -ItemType Directory -Path $report -Force | Out-Null
foreach ($db in $dbs) {
Write-Host "`n=== $($db.Name) ===" -ForegroundColor Cyan
# -ExtendedCheck catches a claims/classic mismatch, which Subscription
# Edition cannot resolve later: classic mode is gone for content web apps.
$issues = Test-SPContentDatabase -Name $db.Name -WebApplication $webApp -ExtendedCheck
$issues | Export-Clixml "$report\$($db.Name).test.xml"
$issues | Format-List | Out-File "$report\$($db.Name).test.txt" -Encoding UTF8
# UpgradeBlocking is the property that separates "fix this now" from
# "write this down". Read the file either way: a non-blocking missing
# web part is still a broken page for whoever put it there.
$blocking = $issues | Where-Object { $_.UpgradeBlocking }
if ($blocking) {
Write-Host "BLOCKED: $($blocking.Count) blocking issue(s). Not mounting." -ForegroundColor Red
$blocking | Format-List Category, Message, Remedy
continue
}
if ($issues) {
Write-Host "$($issues.Count) non-blocking issue(s), logged. Mounting." -ForegroundColor Yellow
}
# Mount-SPContentDatabase, not Central Administration: attaching a database
# through the Central Administration pages is not supported for upgrading.
# Site collections upgrade automatically as part of this, which is the
# default and the recommended behaviour.
Mount-SPContentDatabase -Name $db.Name -WebApplication $webApp -Verbose
Write-Host "MOUNTED: $($db.Name)" -ForegroundColor Green
}
Si una base de datos tiene miles de site collections y la ventana del mount es ajustada, -SkipSiteUpgrade aplaza la actualización de los sitios al primer acceso. Es una herramienta de calendario, no un atajo: el trabajo ocurre igual, solo que repartido y bajo carga de usuarios reales.
Mount-SPContentDatabase -Name 'WSS_Content_Archive' -WebApplication $webApp -SkipSiteUpgrade
Y el modelo cambió. Ya no hay modos de compatibilidad:
"No existe el concepto de 'modos de compatibilidad de site collection' en SharePoint Server Subscription Edition. Debe estar ejecutando siempre la versión más reciente."
Fase 6: qué comprobar antes de dejar entrar a nadie
# 1. Every site collection accounted for, against the inventory.
$before = Import-Csv 'C:\Migration\inventory\sites.csv'
$after = Get-SPSite -Limit All | Select-Object -ExpandProperty Url
$missing = $before.Url | Where-Object { $_ -notin $after }
if ($missing) { $missing | ForEach-Object { Write-Warning "MISSING SITE: $_" } }
else { Write-Host "All $($before.Count) site collections present." -ForegroundColor Green }
# 2. Site collection upgrade status, per site. The logs from Mount-based
# upgrades live inside the Upgrade*.log files, not in separate SiteUpgrade
# files, which is where people go looking and find nothing.
Get-SPSite -Limit All | ForEach-Object {
$info = Get-SPSiteUpgradeSessionInfo -Site $_.Url -ErrorAction SilentlyContinue
[pscustomobject]@{
Url = $_.Url
Status = $info.Status
Errors = $info.ErrorCount
Warnings = $info.WarningCount
}
} | Where-Object { $_.Errors -gt 0 -or $_.Status -ne 'Completed' } | Format-Table -AutoSize
# 3. The index is EMPTY. The topology in the new farm is new, so a full crawl
# over the whole corpus is mandatory, and only once every content database
# is mounted. Starting it earlier just means crawling twice.
$ssa = Get-SPEnterpriseSearchServiceApplication
Get-SPEnterpriseSearchCrawlContentSource -SearchApplication $ssa |
ForEach-Object { $_.StartFullCrawl() }
# 4. Which feature release ring this farm should be on. Standard is the
# default; Early gets new experiences sooner. Record the decision.
Get-SPFeatureReleasePreference
Después, la granja vieja. Déjela en solo lectura y funcionando hasta que la nueva haya pasado una semana laboral completa, porque el rollback más rápido de todo este proyecto es un cambio de DNS de vuelta a una granja que sigue funcionando.
Ensaye primero, y luego hágalo
Todos los números del plan son una suposición hasta que el ensayo los produce. Restaure una copia de las bases de datos de producción en la granja nueva, ejecute la secuencia completa, y anote tres cosas: cuánto tardó cada mount, qué encontró Test-SPContentDatabase -ShowLocation, y cuáles de las features que faltan nadie supo explicar.
Después tire esa granja y hágalo otra vez, en la ventana real. La segunda ejecución es la que tiene tiempos realistas, una lista de soluciones ya completa y ninguna sorpresa en el informe de prueba, porque se encontraron todas en la primera.
Antes de empezar
- Confirme la dirección: 2016 y 2019 van ambos directamente a Subscription Edition, y solo 2013 y anteriores necesitan un salto intermedio
- Compruebe que todas las bases de datos están en 16.0.4351.1000 o superior, porque por debajo la actualización se bloquea de entrada
- Tome el inventario antes de tocar nada, y guárdelo en el control de versiones
- No use el Farm Configuration Wizard para las service applications cuyas bases de datos piensa actualizar
- Reproduzca exactamente las URL antiguas en las web applications nuevas
- Despliegue las farm solutions antes de ejecutar
Test-SPContentDatabase, o el informe será ilegible - Encuentre la passphrase del Secure Store de la granja antigua antes de necesitarla
- Ejecute
Test-SPContentDatabasecon-ExtendedCheck, y lea el informe aunque nada bloquee - Ponga las bases de datos en lectura y escritura después de restaurar, porque una base de solo lectura no puede montarse
- Vuelva a especificar todos los bindings al usar
Set-SPWebApplication, o los que omita revertirán - Planifique el rastreo completo, y planifíquelo para después de que la última base de contenido esté montada
- Mantenga la granja vieja en solo lectura y accesible durante una semana después de la puesta en marcha


