From a66ac345811a35ccb79d9b70e90eddf493951bc2 Mon Sep 17 00:00:00 2001 From: LuigiLink Date: Tue, 25 Aug 2026 17:30:16 +0200 Subject: [PATCH 1/3] refactor: drop the deprecated PSSnapin path, load the SharePointServer module only SharePoint Server 2016 and 2019 reached end of support on 14 July 2026; SPSUpdate now targets Subscription Edition only. - SPSUpdate.ps1 and Invoke-SPSCommand load the SharePointServer module idempotently instead of adding the Microsoft.SharePoint.PowerShell PSSnapin (including inside the remoting HERE-STRING sent to each server). - Start-SPSConfigExe / Start-SPSConfigExeRemote drop the SharePoint 2013 (FileMajorPart 15, 15\BIN, 15.0 hive) branch and the version guard around Upgrade-SPFarm; they target the 16.0 hive and 16\BIN unconditionally. - Start-SPSProductUpdate drops the OSearch15 branch (keeps OSearch16) and the 2016/2019/SE cumulative-update detection; the CU is always Subscription Edition. - Get-SPSLocalVersionInfo no longer takes a ProductVersion parameter and resolves the Subscription Edition product name only. PSScriptAnalyzer clean; 164 Pester tests passing. Refs #26 --- .../Private/Get-SPSLocalVersionInfo.ps1 | 14 ++-------- .../Private/Invoke-SPSCommand.ps1 | 18 ++++-------- .../Public/Start-SPSConfigExe.ps1 | 22 ++++----------- .../Public/Start-SPSConfigExeRemote.ps1 | 24 +++------------- .../Public/Start-SPSProductUpdate.ps1 | 28 ++++--------------- src/SPSUpdate.ps1 | 9 ++---- 6 files changed, 24 insertions(+), 91 deletions(-) diff --git a/src/Modules/SPSUpdate.Common/Private/Get-SPSLocalVersionInfo.ps1 b/src/Modules/SPSUpdate.Common/Private/Get-SPSLocalVersionInfo.ps1 index f94f245..8e7aa77 100644 --- a/src/Modules/SPSUpdate.Common/Private/Get-SPSLocalVersionInfo.ps1 +++ b/src/Modules/SPSUpdate.Common/Private/Get-SPSLocalVersionInfo.ps1 @@ -2,23 +2,13 @@ [OutputType([System.Version])] param ( - # Parameter help description - [Parameter(Mandatory = $true)] - [ValidateSet('2016', '2019', 'SE')] - [System.String] - $ProductVersion, - + # SharePoint Server Subscription Edition is the only supported product version. [Parameter()] [Switch] $IsWssPackage ) - if ($ProductVersion -eq 'SE') { - $spVersion = 'Subscription Edition' - } - else { - $spVersion = $ProductVersion - } + $spVersion = 'Subscription Edition' $productNameRegEx = "Microsoft SharePoint (Foundation|Server) $($spVersion) Core" if ($IsWssPackage) { diff --git a/src/Modules/SPSUpdate.Common/Private/Invoke-SPSCommand.ps1 b/src/Modules/SPSUpdate.Common/Private/Invoke-SPSCommand.ps1 index 6a13db1..1117dd5 100644 --- a/src/Modules/SPSUpdate.Common/Private/Invoke-SPSCommand.ps1 +++ b/src/Modules/SPSUpdate.Common/Private/Invoke-SPSCommand.ps1 @@ -19,22 +19,16 @@ ) $VerbosePreference = 'Continue' - # Base script to ensure the SharePoint snap-in is loaded. On SharePoint 2016/2019 - # the legacy PSSnapin is required; on Subscription Edition the SharePointServer - # module is auto-loaded, so no base script is prepended. - $installedVersion = Get-SPSInstalledProductVersion - if ($installedVersion.ProductMajorPart -eq 15 -or $installedVersion.ProductBuildPart -le 12999) { - $baseScript = @" - if (`$null -eq (Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue)) + # Base script to ensure the SharePointServer module is loaded in the remote session. + # SharePoint Server Subscription Edition exposes its cmdlets through the SharePointServer + # module; load it idempotently before running the caller's script block. + $baseScript = @" + if (`$null -eq (Get-Module -Name SharePointServer)) { - Add-PSSnapin Microsoft.SharePoint.PowerShell + Import-Module SharePointServer -Verbose:`$false -WarningAction SilentlyContinue } "@ - } - else { - $baseScript = '' - } # Prepare the arguments for Invoke-Command $invokeArgs = @{ diff --git a/src/Modules/SPSUpdate.Common/Public/Start-SPSConfigExe.ps1 b/src/Modules/SPSUpdate.Common/Public/Start-SPSConfigExe.ps1 index fa14e06..5e81e28 100644 --- a/src/Modules/SPSUpdate.Common/Public/Start-SPSConfigExe.ps1 +++ b/src/Modules/SPSUpdate.Common/Public/Start-SPSConfigExe.ps1 @@ -2,19 +2,9 @@ [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] param () - # Check which version of SharePoint is installed - $pathToSearch = 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\*\ISAPI\Microsoft.SharePoint.dll' - $fullPath = Get-Item $pathToSearch -ErrorAction SilentlyContinue | Sort-Object { $_.Directory } -Descending | Select-Object -First 1 - $getSPInstalledProductVersion = (Get-Command $fullPath).FileVersionInfo - - if ($getSPInstalledProductVersion.FileMajorPart -eq 15) { - $wssRegKey = 'hklm:SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\15.0\WSS' - $binaryDir = Join-Path $env:CommonProgramFiles "Microsoft Shared\Web Server Extensions\15\BIN" - } - else { - $wssRegKey = 'hklm:SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\16.0\WSS' - $binaryDir = Join-Path $env:CommonProgramFiles "Microsoft Shared\Web Server Extensions\16\BIN" - } + # SharePoint Server Subscription Edition installs under the 16.0 hive. + $wssRegKey = 'hklm:SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\16.0\WSS' + $binaryDir = Join-Path $env:CommonProgramFiles "Microsoft Shared\Web Server Extensions\16\BIN" $psconfigExe = Join-Path -Path $binaryDir -ChildPath "psconfig.exe" # Read LanguagePackInstalled and SetupType registry keys @@ -44,10 +34,8 @@ $count++ } - # Fix for issue with psconfig on SharePoint 2019 - if ($getSPInstalledProductVersion.FileMajorPart -eq 16) { - Upgrade-SPFarm -ServerOnly -SkipDatabaseUpgrade -SkipSiteUpgrade -Confirm:$false - } + # Prepare the farm for the in-place build-to-build upgrade before running psconfig. + Upgrade-SPFarm -ServerOnly -SkipDatabaseUpgrade -SkipSiteUpgrade -Confirm:$false $stdOutTempFile = "$env:TEMP\$((New-Guid).Guid)" $psconfig = Start-Process -FilePath $psconfigExe ` diff --git a/src/Modules/SPSUpdate.Common/Public/Start-SPSConfigExeRemote.ps1 b/src/Modules/SPSUpdate.Common/Public/Start-SPSConfigExeRemote.ps1 index 6dd60ef..69e8dcd 100644 --- a/src/Modules/SPSUpdate.Common/Public/Start-SPSConfigExeRemote.ps1 +++ b/src/Modules/SPSUpdate.Common/Public/Start-SPSConfigExeRemote.ps1 @@ -11,17 +11,8 @@ $InstallAccount ) - # Check which version of SharePoint is installed - $pathToSearch = 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\*\ISAPI\Microsoft.SharePoint.dll' - $fullPath = Get-Item $pathToSearch -ErrorAction SilentlyContinue | Sort-Object { $_.Directory } -Descending | Select-Object -First 1 - $getSPInstalledProductVersion = (Get-Command $fullPath).FileVersionInfo - - if ($getSPInstalledProductVersion.FileMajorPart -eq 15) { - $binaryDir = Join-Path $env:CommonProgramFiles "Microsoft Shared\Web Server Extensions\15\BIN" - } - else { - $binaryDir = Join-Path $env:CommonProgramFiles "Microsoft Shared\Web Server Extensions\16\BIN" - } + # SharePoint Server Subscription Edition installs under the 16.0 hive. + $binaryDir = Join-Path $env:CommonProgramFiles "Microsoft Shared\Web Server Extensions\16\BIN" $psconfigExe = Join-Path -Path $binaryDir -ChildPath "psconfig.exe" # Start wizard @@ -33,11 +24,6 @@ $psconfigExe = $args[0] - # Check which version of SharePoint is installed - $pathToSearch = 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\*\ISAPI\Microsoft.SharePoint.dll' - $fullPath = Get-Item $pathToSearch -ErrorAction SilentlyContinue | Sort-Object { $_.Directory } -Descending | Select-Object -First 1 - $getSPInstalledProductVersion = (Get-Command $fullPath).FileVersionInfo - Write-Verbose -Message "Starting 'Product Version Job' timer job" $pvTimerJob = Get-SPTimerJob -Identity 'job-admin-product-version' $lastRunTime = $pvTimerJob.LastRunTime @@ -55,10 +41,8 @@ $count++ } - # Fix for issue with psconfig on SharePoint 2019 - if ($getSPInstalledProductVersion.FileMajorPart -ne 15) { - Upgrade-SPFarm -ServerOnly -SkipDatabaseUpgrade -SkipSiteUpgrade -Confirm:$false - } + # Prepare the farm for the in-place build-to-build upgrade before running psconfig. + Upgrade-SPFarm -ServerOnly -SkipDatabaseUpgrade -SkipSiteUpgrade -Confirm:$false $stdOutTempFile = "$env:TEMP\$((New-Guid).Guid)" $psconfig = Start-Process -FilePath $psconfigExe ` diff --git a/src/Modules/SPSUpdate.Common/Public/Start-SPSProductUpdate.ps1 b/src/Modules/SPSUpdate.Common/Public/Start-SPSProductUpdate.ps1 index 9c926c1..655c750 100644 --- a/src/Modules/SPSUpdate.Common/Public/Start-SPSProductUpdate.ps1 +++ b/src/Modules/SPSUpdate.Common/Public/Start-SPSProductUpdate.ps1 @@ -40,44 +40,26 @@ Setup file is blocked! Please use 'Unblock-File -Path $SetupFile' to unblock the $fileVersion = $setupFileInfo.VersionInfo.FileVersion Write-Verbose -Message "Update has version $fileVersion" $fileVersionInfo = New-Object -TypeName System.Version -ArgumentList $fileVersion - if ($fileVersionInfo.Build.ToString().Length -eq 4) { - $sharePointVersion = '2016' - } - else { - if ($fileVersionInfo.Build -lt 13000) { - $sharePointVersion = '2019' - } - else { - $sharePointVersion = 'SE' - } - } Write-Verbose -Message "Update is a Cumulative Update." - # For SP 2016 + 2019 Patches + # Subscription Edition cumulative update package. $setupFileInformation = New-Object -TypeName System.IO.FileInfo -ArgumentList $SetupFile if ($setupFileInformation.Name.StartsWith("wssloc")) { Write-Verbose -Message "Cumulative Update is multilingual" - $versionInfo = Get-SPSLocalVersionInfo -ProductVersion $sharePointVersion -IsWssPackage + $versionInfo = Get-SPSLocalVersionInfo -IsWssPackage } else { Write-Verbose -Message "Cumulative Update is generic" - $versionInfo = Get-SPSLocalVersionInfo -ProductVersion $sharePointVersion + $versionInfo = Get-SPSLocalVersionInfo } Write-Verbose -Message "The lowest version of any SharePoint component is $($versionInfo)" if ($versionInfo -lt $fileVersionInfo) { # Version of SharePoint is lower than the patch version. Patch is not installed. Write-Verbose -Message "The version of SharePoint installed is lower than the update. Starting update process." - $installedVersion = Get-SPSInstalledProductVersion if ($ShutdownServices) { - $listOfServices = @("SPSearchHostController", "SPTimerV4", "IISADMIN") - if ($installedVersion.ProductMajorPart -eq 15) { - - $listOfServices += "OSearch15" - } - else { - $listOfServices += "OSearch16" - } + # Subscription Edition search service instance is OSearch16. + $listOfServices = @("SPSearchHostController", "SPTimerV4", "IISADMIN", "OSearch16") Write-Verbose -Message "Gettings services status before stopping services for installation." $servicesStatusFilePath = Join-Path -Path $PSScriptRoot -ChildPath "ServicesStatus_$($env:COMPUTERNAME)_$(Get-Date -Format 'yyyyMMddHHmmss').json" Get-Service -Name $listOfServices -ErrorAction SilentlyContinue | Select-Object Name, StartType, Status | ConvertTo-Json | Set-Content -Path $servicesStatusFilePath -Force diff --git a/src/SPSUpdate.ps1 b/src/SPSUpdate.ps1 index 6378035..44e877b 100644 --- a/src/SPSUpdate.ps1 +++ b/src/SPSUpdate.ps1 @@ -347,16 +347,11 @@ Write-Output '-----------------------------------------------' Write-Verbose -Message "Setting power management plan to 'High Performance'..." Start-Process -FilePath "$env:SystemRoot\system32\powercfg.exe" -ArgumentList '/s 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c' -NoNewWindow -# 1. Load SharePoint Powershell Snapin or Import-Module +# 1. Load the SharePointServer module (SharePoint Server Subscription Edition) try { $installedVersion = Get-SPSInstalledProductVersion Write-Output "Installed SharePoint Product Version: $($installedVersion.FileVersion)" - if ($installedVersion.ProductMajorPart -eq 15 -or $installedVersion.ProductBuildPart -le 12999) { - if ($null -eq (Get-PSSnapin -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue)) { - Add-PSSnapin Microsoft.SharePoint.PowerShell - } - } - else { + if ($null -eq (Get-Module -Name SharePointServer)) { Import-Module SharePointServer -Verbose:$false -WarningAction SilentlyContinue } } From aaeb5ad6a25a7dc1d0f37b87dd3490975f8b3030 Mon Sep 17 00:00:00 2001 From: LuigiLink Date: Tue, 25 Aug 2026 17:31:26 +0200 Subject: [PATCH 2/3] docs: update documentation for Subscription Edition only - README, wiki Home and the offline install guide now state SharePoint Server Subscription Edition as the only supported product, with a note that 2016/2019 reached end of support on 14 July 2026 and users on those versions must use the previous major release (v4.2.0). - Usage wiki: keep the 2019 -> Subscription Edition migration context and add a note that running InitContentDB on a 2019 source farm requires v4.2.0. - Remove the '2016/2019 snap-in vs SE module' wording from the offline guide. Refs #26 --- README.md | 4 +++- src/SPSUpdate_README.md | 10 +++++++--- wiki/Home.md | 4 +++- wiki/Usage.md | 4 ++++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9a0bef8..10253f6 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,9 @@ **SPSUpdate** is a PowerShell tool that installs SharePoint Server cumulative updates and runs the post-setup Configuration Wizard (PSConfig) across a farm. It installs the binaries, mounts/upgrades content databases in parallel, runs PSConfig on local and remote servers over CredSSP remoting, and configures the side-by-side token for zero-downtime patching. -Compatible with SharePoint Server **2016**, **2019**, and **Subscription Edition**. Requires PowerShell 5.1 or later — no DSC module needed. +Compatible with **SharePoint Server Subscription Edition**. Requires PowerShell 5.1 or later — no DSC module needed. + +> SharePoint Server 2016 and 2019 reached end of support on 14 July 2026. If you still run those versions, use the previous major release [v4.2.0](https://github.com/luigilink/SPSUpdate/releases/tag/v4.2.0) — including to generate the ContentDatabase inventory (`-Action InitContentDB`) on a 2019 source farm during a 2019 → Subscription Edition migration. ## Quick links diff --git a/src/SPSUpdate_README.md b/src/SPSUpdate_README.md index 4b19b62..f413101 100644 --- a/src/SPSUpdate_README.md +++ b/src/SPSUpdate_README.md @@ -8,9 +8,14 @@ SharePoint environment. > This guide ships inside the release package so it is available offline on the server. > For the full online documentation, see the [SPSUpdate Wiki](https://github.com/luigilink/SPSUpdate/wiki). +> **Subscription Edition only.** SharePoint Server 2016 and 2019 reached end of support on +> 14 July 2026. If you still run those versions (including generating the ContentDatabase +> inventory on a 2019 source farm during a migration), use the previous major release +> v4.2.0. + ## 📦 Prerequisites -- SharePoint Server 2016, 2019 or Subscription Edition +- SharePoint Server Subscription Edition - Administrator privileges on the server - PowerShell 5.1 or later (no DSC module required) - A service account (`InstallAccount`) for the scheduled tasks and CredSSP remoting @@ -200,8 +205,7 @@ E:\SCRIPT\SPSUpdate.ps1 -Action Uninstall -ConfigFile 'E:\SCRIPT\Config\CONTOSO- - Creates a `Logs` folder and a per-run transcript (sequence/action-aware naming). - Verifies the script runs with Administrator rights before proceeding. -- Detects the installed SharePoint version (`Get-SPSInstalledProductVersion`) and loads the - appropriate SharePoint snap-in (2016/2019) or the `SharePointServer` module (SE). +- Loads the `SharePointServer` module (SharePoint Server Subscription Edition). - Full mode creates four sequence tasks (`SPSUpdate-Sequence1..4`) and starts them in parallel (with short random sleeps to avoid OWSTimer conflicts). - Remote operations (PSConfig, side-by-side) use CredSSP and fail with a clear error if the diff --git a/wiki/Home.md b/wiki/Home.md index b3717fa..e5757ad 100644 --- a/wiki/Home.md +++ b/wiki/Home.md @@ -1,6 +1,8 @@ # SPSUpdate Wiki -**SPSUpdate** is a PowerShell tool that installs SharePoint Server cumulative updates and runs the post-setup Configuration Wizard (PSConfig) across a farm. It is compatible with all supported on-premises versions of SharePoint Server (2016 to Subscription Edition) and requires only PowerShell 5.1 or later — there is no DSC dependency. +**SPSUpdate** is a PowerShell tool that installs SharePoint Server cumulative updates and runs the post-setup Configuration Wizard (PSConfig) across a farm. It targets **SharePoint Server Subscription Edition** and requires only PowerShell 5.1 or later — there is no DSC dependency. + +> SharePoint Server 2016 and 2019 reached end of support on 14 July 2026. For those versions, use the previous major release [v4.2.0](https://github.com/luigilink/SPSUpdate/releases/tag/v4.2.0). SPSUpdate installs the update binaries, mounts and/or upgrades content databases in parallel via scheduled tasks, runs PSConfig on the local and remote servers over **CredSSP remoting**, and configures the side-by-side patching token for zero-downtime upgrades. diff --git a/wiki/Usage.md b/wiki/Usage.md index 812919a..f38bbff 100644 --- a/wiki/Usage.md +++ b/wiki/Usage.md @@ -66,6 +66,10 @@ is typically used on the source farm before a farm upgrade (for example SharePoi 2019 → Subscription Edition) so the inventory can be copied to the target farm and consumed by the `MountContentDatabase` flow. +> Since v5.0.0 SPSUpdate is Subscription Edition only. To run `InitContentDB` on a +> **SharePoint Server 2019 source farm** during a 2019 → Subscription Edition migration, use +> the previous major release [v4.2.0](https://github.com/luigilink/SPSUpdate/releases/tag/v4.2.0). + It also writes a self-contained HTML report of the inventory under `Results\` (see below). ## ContentDatabase inventory report From 9f0f3a48caa720f17708ce0cc34b8c2330918e78 Mon Sep 17 00:00:00 2001 From: LuigiLink Date: Tue, 25 Aug 2026 17:32:28 +0200 Subject: [PATCH 3/3] chore: bump to 5.0.0 (breaking: SE-only) - SPSUpdate.Common manifest ModuleVersion -> 5.0.0. - CHANGELOG: prepend the [5.0.0] section (Removed / Changed / Migration). - RELEASE-NOTES: replace with the 5.0.0 notes only (GitHub Release body). - Tests: bump the module version guard to 5.0.0. Refs #26 --- CHANGELOG.md | 17 +++++ RELEASE-NOTES.md | 62 +++++-------------- .../SPSUpdate.Common/SPSUpdate.Common.psd1 | 2 +- tests/SPSUpdate.Common.Tests.ps1 | 4 +- 4 files changed, 35 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78ee1bd..1bd65b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,23 @@ The format is based on and uses the types of changes according to [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [5.0.0] - 2026-08-25 + +### Removed + +- **BREAKING** — Support for SharePoint Server 2016 and 2019 (both reached end of support on 14 July 2026). SPSUpdate now targets SharePoint Server Subscription Edition only. +- The deprecated `Microsoft.SharePoint.PowerShell` PSSnapin path: `SPSUpdate.ps1` and `Invoke-SPSCommand` load the `SharePointServer` module only (idempotently, including inside the remoting HERE-STRING). +- The legacy SharePoint 2013 branches (`FileMajorPart`/`ProductMajorPart -eq 15`: `15\BIN`, the `15.0` registry hive and `OSearch15`) and the 2016/2019/SE cumulative-update detection in `Start-SPSConfigExe`, `Start-SPSConfigExeRemote` and `Start-SPSProductUpdate`. +- The `ProductVersion` parameter of `Get-SPSLocalVersionInfo` (Subscription Edition is resolved unconditionally). + +### Changed + +- **BREAKING** — Major version bump to `5.0.0`. `Start-SPSConfigExe`/`Start-SPSConfigExeRemote` target the `16.0` hive and `16\BIN` and run `Upgrade-SPFarm` unconditionally; `Start-SPSProductUpdate` stops `OSearch16`. + +### Migration + +- Users still running SharePoint Server 2016 or 2019 must use the previous major release **v4.2.0**. In particular, generating the ContentDatabase inventory (`-Action InitContentDB`) on a 2019 source farm as part of a 2019 → Subscription Edition migration must be done with v4.2.0. + ## [4.2.0] - 2026-06-30 ### Added diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index ac7dbbc..1bb8b49 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -1,56 +1,24 @@ # SPSUpdate - Release Notes -## [4.2.0] - 2026-06-30 - -This release adds a near real-time patching dashboard: while a cumulative update is rolled -out across the farm, SPSUpdate records the progress of every phase into a shared status -store and the master assembles a self-contained, auto-refreshing HTML dashboard. - -### Added - -- Status store and dashboard functions: `Set-SPSUpdateStatus` / `Get-SPSUpdateStatus` - (atomic per-scope JSON store, each writer owns its file), `Get-SPSStatusCampaignPath` - (resolves `\--`), and `Export-SPSUpdateProgressReport` (renders a - self-contained HTML dashboard with overall state, per-phase sections, colored state - badges, per-item exit codes and per-sequence percentage; meta-refresh while running). -- New optional `StatusStorePath` config key (UNC share) with a local `Results\status` - fallback. -- New `-Action ResetStatus` to clear a campaign before a fresh patching round. -- `SPSUpdate.ps1` is instrumented end-to-end: ProductUpdate per server (per-setup-file - items), the four mount/upgrade sequences (per-database items and a running percentage), - the Configuration Wizard per server (local and remote), and side-by-side. The master - regenerates the dashboard on every wait-loop iteration and writes a final completed - dashboard with auto-refresh off. -- New `Test-SPSUpdateReadiness.ps1` pre-flight check (module, config, DPAPI secret, - elevation, status store write access, per-server CredSSP reachability). The status store - check probes write access **both as the current user and as the InstallAccount**, since the - upgrade sequences run as the service account and only appear on the dashboard when it can - write to the share. -- The dashboard collapses finished scopes (Done/Skipped) by default and keeps active ones - expanded (native `
`/``, accessible, no JS); each collapsed line still - shows its badge, percentage and an `N/M done` count. -- Real process exit codes are surfaced: the ProductUpdate item's Exit column shows the - setup.exe code (`0`, `17022` = reboot required, ...), and the Configuration Wizard records - the psconfig.exe code in its detail (`PSConfig completed (exit 0)`). - -### How to use - -1. Set `StatusStorePath` to a UNC share writable by the InstallAccount from every server - (grant it **Modify** on the SMB share and NTFS — the sequence tasks run as that account). -2. Run `Test-SPSUpdateReadiness.ps1` to confirm the environment (both write probes green). -3. `SPSUpdate.ps1 -ConfigFile '.psd1' -Action ResetStatus` to start a clean campaign. -4. Open `\--\_dashboard.html` in a browser. -5. Run `-Action ProductUpdate` on each server, then the default master run; watch the - dashboard update itself. +## [5.0.0] - 2026-08-25 + +This is a **breaking** release: SPSUpdate now targets **SharePoint Server Subscription +Edition only**. SharePoint Server 2016 and 2019 both reached end of support on +14 July 2026. + +### Removed + +- **BREAKING** — Support for SharePoint Server 2016 and 2019. SPSUpdate now targets SharePoint Server Subscription Edition only. +- The deprecated `Microsoft.SharePoint.PowerShell` PSSnapin path: `SPSUpdate.ps1` and `Invoke-SPSCommand` load the `SharePointServer` module only (idempotently, including inside the remoting HERE-STRING). +- The legacy SharePoint 2013 branches (`FileMajorPart`/`ProductMajorPart -eq 15`: `15\BIN`, the `15.0` registry hive and `OSearch15`) and the 2016/2019/SE cumulative-update detection in `Start-SPSConfigExe`, `Start-SPSConfigExeRemote` and `Start-SPSProductUpdate`. +- The `ProductVersion` parameter of `Get-SPSLocalVersionInfo` (Subscription Edition is resolved unconditionally). ### Changed -- Bumped the module manifest to `4.2.0` and exported the new functions. +- **BREAKING** — Major version bump to `5.0.0`. `Start-SPSConfigExe`/`Start-SPSConfigExeRemote` target the `16.0` hive and `16\BIN` and run `Upgrade-SPFarm` unconditionally; `Start-SPSProductUpdate` stops `OSearch16`. -### Notes +### Migration -- Validated end-to-end on a real three-server Subscription Edition farm with an actual - cumulative update (binary install, parallel content-database upgrade, and the post-setup - Configuration Wizard, all reflected live on the dashboard). +- Users still running SharePoint Server 2016 or 2019 must use the previous major release **v4.2.0**. In particular, generating the ContentDatabase inventory (`-Action InitContentDB`) on a 2019 source farm as part of a 2019 → Subscription Edition migration must be done with v4.2.0. A full list of changes in each version can be found in the [change log](CHANGELOG.md) diff --git a/src/Modules/SPSUpdate.Common/SPSUpdate.Common.psd1 b/src/Modules/SPSUpdate.Common/SPSUpdate.Common.psd1 index b2fb943..50f8dcd 100644 --- a/src/Modules/SPSUpdate.Common/SPSUpdate.Common.psd1 +++ b/src/Modules/SPSUpdate.Common/SPSUpdate.Common.psd1 @@ -1,6 +1,6 @@ @{ RootModule = 'SPSUpdate.Common.psm1' - ModuleVersion = '4.2.0' + ModuleVersion = '5.0.0' GUID = 'd6f4e2b7-3a1c-4d8e-9f2a-6c5b7e0a1d34' Author = 'Jean-Cyril DROUHIN' CompanyName = 'luigilink' diff --git a/tests/SPSUpdate.Common.Tests.ps1 b/tests/SPSUpdate.Common.Tests.ps1 index 8905e09..63d04ae 100644 --- a/tests/SPSUpdate.Common.Tests.ps1 +++ b/tests/SPSUpdate.Common.Tests.ps1 @@ -36,8 +36,8 @@ Describe 'SPSUpdate.Common module' { { Test-ModuleManifest -Path $modulePath -ErrorAction Stop } | Should -Not -Throw } - It 'manifest version is 4.0.0 or higher' { - (Test-ModuleManifest -Path $modulePath).Version | Should -BeGreaterOrEqual ([version]'4.2.0') + It 'manifest version is 5.0.0 or higher' { + (Test-ModuleManifest -Path $modulePath).Version | Should -BeGreaterOrEqual ([version]'5.0.0') } It 'exports exactly the expected public functions' {