Speeding up SharePoint Subscription Edition CU installation
Speeding up SharePoint Subscription Edition CU installation
1) It seems like Miguel Isidoro has a pretty good blog post about
speeding up SharePoint CU installation.
However, it hasn't been updated for SharePoint Subscription Edition, yet.
2) The SharePoint CU Installer script hasn't been updated for
SharePoint Subscription edition, which no longer requires two separate patches
for the language pack (wssloc patch) and SharePoint itself (sts patch).
With SP SE patches, you only need one patch file with the uber prefix.
For example: uber-subscription-kb5002581-fullfile-x64-glb.exe
Latest patches can be found at Microsoft Learn:
SharePoint
updates - Office release notes | Microsoft Learn
To download the
SharePoint Patch PowerShell script, click here. This script, written by Trevor
Seward, is an improved version of a PowerShell
script originally
created by Russ Maxwell for SharePoint 2013.
The SharePointPatch
comes with a number of useful functions. One of them is the
Install-SPPatch. Here is the original Install-SPPatch that checks for
wssloc and sts patches.
<#
.SYNOPSIS
Install-SPPatch
.DESCRIPTION
Install-SPPatch reduces the
amount of time it takes to install SharePoint patches. This cmdlet supports
SharePoint 2013 and above. Additional information
can be found at
https://github.com/Nauplius.
.PARAMETER Path
The folder where the patch
file(s) reside.
.PARAMETER Pause
Pauses the Search Service
Application(s) prior to stopping the SharePoint Search Services.
.PARAMETER Stop
Stop the SharePoint Search
Services without pausing the Search Service Application(s).
.PARAMETER SilentInstall
Silently installs the patches
without user input. Not specifying this parameter will cause each patch to
prompt to install.
.PARAMETER KeepSearchPaused
Keeps the Search Service
Application(s) in a paused state after the installation of the patch has
completed. Useful for when applying the patch to multiple
servers in the farm. Default to
false.
.PARAMETER OnlySTS
Only apply the STS
(non-language dependent) patch. This switch may be used when only an STS patch
is available.
.EXAMPLE
Install-SPPatch -Path
C:\Updates -Pause -SilentInstall
Install the available patches
in C:\Updates, pauses the Search Service Application(s) on the farm, and
performs a silent installation.
.EXAMPLE
Install-SPPatch -Path
C:\Updates -Pause -KeepSearchPaused:$true -SilentInstall
Install the available patches
in C:\Updates, pauses the Search Service Application(s) on the farm,
does not resume the Search
Service Application(s) after the installation is complete, and performs a
silent installation.
.NOTES
Author: Trevor Seward
Date: 01/16/2020
.LINK
https://thesharepointfarm.com
.LINK
https://github.com/Nauplius
.LINK
https://sharepointupdates.com
#>
Function Install-SPPatch {
param
(
[string]
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
$Path,
[switch]
[Parameter(Mandatory = $true, ParameterSetName = "PauseSearch")]
$Pause,
[switch]
[Parameter(Mandatory = $true, ParameterSetName = "StopSearch")]
$Stop,
[switch]
[Parameter(Mandatory = $false, ParameterSetName = "PauseSearch")]
$KeepSearchPaused = $false,
[switch]
[Parameter(Mandatory = $false)]
$SilentInstall,
[switch]
[Parameter(Mandatory = $false)]
$OnlySTS
)
$version = (Get-SPFarm).BuildVersion
$majorVersion = $version.Major
$startTime = Get-Date
$exitRebootCodes = @(3010, 17022)
$searchSvcRunning = $false
Write-Host -ForegroundColor Green "Current build: $version"
###########################
##Ensure Patch is Present##
###########################
if ($majorVersion -eq '16') {
$sts = Get-ChildItem -LiteralPath $Path -Filter *.exe | ? { $_.Name -match 'sts([A-Za-z0-9\-]+).exe' }
$wssloc = Get-ChildItem -LiteralPath $Path -Filter *.exe | ? { $_.Name -match 'wssloc([A-Za-z0-9\-]+).exe' }
if ($OnlySTS) {
if ($sts -eq $null) {
Write-Host 'Missing the sts patch. Please make sure the sts
patch present in the specified directory.' -ForegroundColor Red
return
}
}
else {
if ($sts -eq $null -and $wssloc -eq $null) {
Write-Host 'Missing the sts and wssloc patch. Please make sure
both patches are present in the specified directory.' -ForegroundColor Red
return
}
if ($sts -eq $null -or $wssloc -eq $null) {
Write-Host '[Warning] Either the sts and wssloc patch is not
available. Please make sure both patches are present in the same directory or
safely ignore if only single patch is available.' -ForegroundColor Yellow
return
}
}
if ($OnlySTS) {
$patchfiles = $sts
Write-Host -for Yellow "Installing $sts"
}
else {
$patchfiles = $sts, $wssloc
Write-Host -for Yellow "Installing $sts and $wssloc"
}
}
elseif ($majorVersion -eq '15') {
$patchfiles = Get-ChildItem -LiteralPath $Path -Filter *.exe | ? { $_.Name -match '([A-Za-z0-9\-]+)2013-kb([A-Za-z0-9\-]+)glb.exe' }
if ($patchfiles -eq $null) {
Write-Host 'Unable to retrieve the file(s). Exiting Script' -ForegroundColor Red
return
}
Write-Host -ForegroundColor Yellow "Installing $patchfiles"
}
elseif ($majorVersion -lt '15') {
throw 'This cmdlet supports SharePoint 2013 and above.'
}
########################
##Stop Search Services##
########################
##Checking Search services##
$oSearchSvc = Get-Service "OSearch$majorVersion"
$sPSearchHCSvc = Get-Service "SPSearchHostController"
if (($oSearchSvc.status -eq 'Running') -or ($sPSearchHCSvc.status -eq 'Running')) {
$searchSvcRunning = $true
if ($Pause) {
$ssas = Get-SPEnterpriseSearchServiceApplication
foreach ($ssa in $ssas) {
Write-Host -ForegroundColor Yellow "Pausing the Search Service Application:
$($ssa.DisplayName)"
Write-Host -ForegroundColor Yellow ' This could take a few minutes...'
Suspend-SPEnterpriseSearchServiceApplication -Identity $ssa | Out-Null
}
}
elseif ($Stop) {
Write-Host -ForegroundColor Cyan ' Continuing without pausing the Search Service Application'
}
}
#We don't need to stop SharePoint
Services for 2016 and above
if ($majorVersion -lt '16') {
Write-Host -ForegroundColor Yellow 'Stopping Search Services if they are running'
if ($oSearchSvc.status -eq 'Running') {
Set-Service -Name "OSearch$majorVersion" -StartupType Disabled
Stop-Service "OSearch$majorVersion" -WA 0
}
if ($sPSearchHCSvc.status -eq 'Running') {
Set-Service 'SPSearchHostController' -StartupType Disabled
Stop-Service 'SPSearchHostController' -WA 0
}
Write-Host -ForegroundColor Green 'Search Services are Stopped'
Write-Host
#######################
##Stop Other Services##
#######################
Set-Service -Name 'IISADMIN' -StartupType Disabled
Set-Service -Name 'SPTimerV4' -StartupType Disabled
Write-Host -ForegroundColor Green 'Gracefully stopping IIS...'
Write-Host
iisreset -stop -noforce
Write-Host -ForegroundColor Yellow 'Stopping SPTimerV4'
Write-Host
$sPTimer = Get-Service 'SPTimerV4'
if ($sPTimer.Status -eq 'Running') {
Stop-Service 'SPTimerV4'
}
Write-Host -ForegroundColor Green 'Services are Stopped'
Write-Host
Write-Host
}
##################
##Start patching##
##################
Write-Host -ForegroundColor Yellow 'Working on it... Please keep this PowerShell window open...'
Write-Host
$patchStartTime = Get-Date
foreach ($patchfile in $patchfiles) {
$filename = $patchfile.Fullname
#unblock the file, to get rid of the
prompts
Unblock-File -Path $filename -Confirm:$false
if ($SilentInstall) {
$process = Start-Process $filename -ArgumentList '/passive /quiet' -PassThru -Wait
}
else {
$process = Start-Process $filename -ArgumentList '/norestart' -PassThru -Wait
}
if ($exitRebootCodes.Contains($process.ExitCode)) {
$reboot = $true
}
Write-Host -ForegroundColor Yellow "Patch $patchfile installed with Exit Code
$($process.ExitCode)"
}
$patchEndTime = Get-Date
Write-Host
Write-Host -ForegroundColor Yellow ('Patch installation completed in {0:g}' -f ($patchEndTime - $patchStartTime))
Write-Host
if ($majorVersion -lt '16') {
##################
##Start Services##
##################
Write-Host -ForegroundColor Yellow 'Starting Services'
Set-Service -Name 'SPTimerV4' -StartupType Automatic
Set-Service -Name 'IISADMIN' -StartupType Automatic
Start-Service 'SPTimerV4'
Start-Service 'IISAdmin'
###Ensuring Search Services were
stopped by script before Starting"
if ($searchSvcRunning = $true) {
Set-Service -Name "OSearch$majorVersion" -StartupType Manual
Start-Service "OSearch$majorVersion" -WA 0
Set-Service 'SPSearchHostController' -StartupType Automatic
Start-Service 'SPSearchHostController' -WA 0
}
}
###Resuming Search Service Application
if paused###
if ($Pause -and $KeepSearchPaused -eq $false) {
$ssas = Get-SPEnterpriseSearchServiceApplication
foreach ($ssa in $ssas) {
Write-Host -ForegroundColor Yellow "Resuming the Search Service Application:
$($ssa.DisplayName)"
Write-Host -ForegroundColor Yellow ' This could take a few minutes...'
Resume-SPEnterpriseSearchServiceApplication -Identity $ssa | Out-Null
}
}
elseif ($pause -and $KeepSearchPaused -eq $true) {
Write-Host -ForegroundColor Yellow 'Not resuming the Search Service Application(s)'
}
###Resuming IIS###
iisreset -start
$endTime = Get-Date
Write-Host -ForegroundColor Green 'Services are Started'
Write-Host
Write-Host
Write-Host -ForegroundColor Yellow ('Script completed in {0:g}' -f ($endTime - $startTime))
Write-Host -ForegroundColor Yellow 'Started:' $startTime
Write-Host -ForegroundColor Yellow 'Finished:' $endTime
if ($reboot) {
Write-Host -ForegroundColor Yellow 'A reboot is required'
}
}
I modified my copy version of this script so that the
script no longer requires both the sts and wssloc patches.
<#
.SYNOPSIS
Install-SPPatch
.DESCRIPTION
Install-SPPatch reduces the amount of time it takes to
install SharePoint patches. This cmdlet supports SharePoint 2013 and above.
Additional information
can be found at https://github.com/Nauplius.
.PARAMETER Path
The folder where the patch file(s) reside.
.PARAMETER Pause
Pauses the Search Service Application(s) prior to stopping
the SharePoint Search Services.
.PARAMETER Stop
Stop the SharePoint Search Services without pausing the
Search Service Application(s).
.PARAMETER SilentInstall
Silently installs the patches without user input. Not
specifying this parameter will cause each patch to prompt to install.
.PARAMETER KeepSearchPaused
Keeps the Search Service Application(s) in a paused state
after the installation of the patch has completed. Useful for when applying the
patch to multiple
servers in the farm. Default to false.
.PARAMETER OnlySTS
Only apply the STS (non-language dependent) patch. This
switch may be used when only an STS patch is available.
.EXAMPLE
Install-SPPatch -Path C:\Updates -Pause -SilentInstall
Install the available patches in C:\Updates, pauses the
Search Service Application(s) on the farm, and performs a silent installation.
.EXAMPLE
Install-SPPatch -Path C:\Updates -Pause
-KeepSearchPaused:$true -SilentInstall
Install the available patches in C:\Updates, pauses the
Search Service Application(s) on the farm,
does not resume the Search Service Application(s) after
the installation is complete, and performs a silent installation.
.NOTES
Author: Trevor Seward
Date: 01/16/2020
.LINK
https://thesharepointfarm.com
.LINK
https://github.com/Nauplius
.LINK
https://sharepointupdates.com
#>
Function
Install-SPPatch {
param
(
[string]
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
$Path,
[switch]
[Parameter(Mandatory = $true, ParameterSetName =
"PauseSearch")]
$Pause,
[switch]
[Parameter(Mandatory = $true, ParameterSetName =
"StopSearch")]
$Stop,
[switch]
[Parameter(Mandatory = $false, ParameterSetName =
"PauseSearch")]
$KeepSearchPaused = $false,
[switch]
[Parameter(Mandatory = $false)]
$SilentInstall,
[switch]
[Parameter(Mandatory = $false)]
$OnlySTS
)
$version = (Get-SPFarm).BuildVersion
$majorVersion = $version.Major
$build = $version.Build;
$startTime = Get-Date
$exitRebootCodes = @(3010, 17022)
$searchSvcRunning = $false
Write-Host -ForegroundColor Green "Current build: $version"
###########################
##Ensure Patch is Present##
###########################
if ($majorVersion -eq '16' -and $build -ge 15601)
{
$sts = Get-ChildItem
-LiteralPath $Path -Filter *.exe | ? { $_.Name -match
'sts([A-Za-z0-9\-]+).exe' }
$wssloc = Get-ChildItem
-LiteralPath $Path -Filter *.exe | ? { $_.Name -match
'wssloc([A-Za-z0-9\-]+).exe' }
$uberloc = Get-ChildItem
-LiteralPath $Path -Filter *.exe | ? { $_.Name -match
'uber([A-Za-z0-9\-]+).exe' }
if ($uberloc -ne $null)
{
$patchfiles =
$uberloc;
Write-Host -for
Yellow "Installing $uberloc";
}
else
{
if ($OnlySTS) {
if
($sts -eq $null) {
Write-Host 'Missing the sts patch. Please make sure the sts patch
present in the specified directory.' -ForegroundColor Red
return
}
}
else {
if
($sts -eq $null -and $wssloc -eq $null) {
Write-Host 'Missing the sts and wssloc patch. Please make sure
both patches are present in the specified directory.' -ForegroundColor Red
return
}
if
($sts -eq $null -or $wssloc -eq $null) {
Write-Host '[Warning] Either the sts and wssloc patch is not
available. Please make sure both patches are present in the same directory or
safely ignore if only single patch is available.' -ForegroundColor Yellow
return
}
}
if ($OnlySTS) {
$patchfiles = $sts
Write-Host -for Yellow "Installing $sts"
}
else {
$patchfiles = $sts, $wssloc
Write-Host -for Yellow "Installing $sts and $wssloc"
}
}
}
elseif ($majorVersion -eq '16') {
$sts = Get-ChildItem -LiteralPath $Path -Filter
*.exe | ? { $_.Name -match 'sts([A-Za-z0-9\-]+).exe' }
$wssloc = Get-ChildItem -LiteralPath $Path -Filter
*.exe | ? { $_.Name -match 'wssloc([A-Za-z0-9\-]+).exe' }
$uberloc = Get-ChildItem -LiteralPath $Path -Filter
*.exe | ? { $_.Name -match 'uber([A-Za-z0-9\-]+).exe' }
if ($OnlySTS) {
if ($sts -eq $null) {
Write-Host 'Missing the sts
patch. Please make sure the sts patch present in the specified directory.'
-ForegroundColor Red
return
}
}
else {
if ($sts -eq $null -and $wssloc -eq $null) {
Write-Host 'Missing the sts
and wssloc patch. Please make sure both patches are present in the specified
directory.' -ForegroundColor Red
return
}
if ($sts -eq $null -or $wssloc -eq $null) {
Write-Host '[Warning] Either
the sts and wssloc patch is not available. Please make sure both patches are
present in the same directory or safely ignore if only single patch is
available.' -ForegroundColor Yellow
return
}
}
if ($OnlySTS) {
$patchfiles = $sts
Write-Host -for Yellow "Installing
$sts"
}
else {
$patchfiles = $sts, $wssloc
Write-Host -for Yellow "Installing $sts
and $wssloc"
}
}
elseif ($majorVersion -eq '15') {
$patchfiles = Get-ChildItem -LiteralPath $Path
-Filter *.exe | ? { $_.Name -match
'([A-Za-z0-9\-]+)2013-kb([A-Za-z0-9\-]+)glb.exe' }
if ($patchfiles -eq $null) {
Write-Host 'Unable to retrieve the
file(s). Exiting Script' -ForegroundColor Red
return
}
Write-Host -ForegroundColor Yellow "Installing
$patchfiles"
}
elseif ($majorVersion -lt '15') {
throw 'This cmdlet supports SharePoint 2013 and above.'
}
########################
##Stop Search Services##
########################
##Checking Search services##
$oSearchSvc = Get-Service "OSearch$majorVersion"
$sPSearchHCSvc = Get-Service "SPSearchHostController"
if (($oSearchSvc.status -eq 'Running') -or ($sPSearchHCSvc.status -eq
'Running')) {
$searchSvcRunning = $true
if ($Pause) {
$ssas =
Get-SPEnterpriseSearchServiceApplication
foreach ($ssa in $ssas) {
Write-Host -ForegroundColor
Yellow "Pausing the Search Service Application: $($ssa.DisplayName)"
Write-Host
-ForegroundColor Yellow ' This could take a few minutes...'
Suspend-SPEnterpriseSearchServiceApplication -Identity $ssa | Out-Null
}
}
elseif ($Stop) {
Write-Host -ForegroundColor Cyan '
Continuing without pausing the Search Service Application'
}
}
#We don't need to stop SharePoint Services for 2016 and above
if ($majorVersion -lt '16') {
Write-Host -ForegroundColor Yellow 'Stopping Search
Services if they are running'
if ($oSearchSvc.status -eq 'Running') {
Set-Service -Name
"OSearch$majorVersion" -StartupType Disabled
Stop-Service
"OSearch$majorVersion" -WA 0
}
if ($sPSearchHCSvc.status -eq 'Running') {
Set-Service 'SPSearchHostController'
-StartupType Disabled
Stop-Service 'SPSearchHostController' -WA 0
}
Write-Host -ForegroundColor Green 'Search Services are
Stopped'
Write-Host
#######################
##Stop Other Services##
#######################
Set-Service -Name 'IISADMIN' -StartupType Disabled
Set-Service -Name 'SPTimerV4' -StartupType Disabled
Write-Host -ForegroundColor Green 'Gracefully stopping
IIS...'
Write-Host
iisreset -stop -noforce
Write-Host -ForegroundColor Yellow 'Stopping SPTimerV4'
Write-Host
$sPTimer = Get-Service 'SPTimerV4'
if ($sPTimer.Status -eq 'Running') {
Stop-Service 'SPTimerV4'
}
Write-Host -ForegroundColor Green 'Services are Stopped'
Write-Host
Write-Host
}
##################
##Start patching##
##################
Write-Host -ForegroundColor Yellow 'Working on it... Please keep this
PowerShell window open...'
Write-Host
$patchStartTime = Get-Date
foreach ($patchfile in $patchfiles) {
$filename = $patchfile.Fullname
#unblock the file, to get rid of the prompts
Unblock-File -Path $filename -Confirm:$false
if ($SilentInstall) {
$process = Start-Process $filename
-ArgumentList '/passive /quiet' -PassThru -Wait
}
else {
$process = Start-Process $filename
-ArgumentList '/norestart' -PassThru -Wait
}
if ($exitRebootCodes.Contains($process.ExitCode)) {
$reboot = $true
}
Write-Host -ForegroundColor Yellow "Patch $patchfile
installed with Exit Code $($process.ExitCode)"
}
$patchEndTime = Get-Date
Write-Host
Write-Host -ForegroundColor Yellow ('Patch installation completed in
{0:g}' -f ($patchEndTime - $patchStartTime))
Write-Host
if ($majorVersion -lt '16') {
##################
##Start Services##
##################
Write-Host -ForegroundColor Yellow 'Starting Services'
Set-Service -Name 'SPTimerV4' -StartupType Automatic
Set-Service -Name 'IISADMIN' -StartupType Automatic
Start-Service 'SPTimerV4'
Start-Service 'IISAdmin'
###Ensuring Search Services were stopped by script before
Starting"
if ($searchSvcRunning = $true) {
Set-Service -Name
"OSearch$majorVersion" -StartupType Manual
Start-Service
"OSearch$majorVersion" -WA 0
Set-Service 'SPSearchHostController'
-StartupType Automatic
Start-Service 'SPSearchHostController' -WA 0
}
}
###Resuming Search Service Application if paused###
if ($Pause -and $KeepSearchPaused -eq $false) {
$ssas = Get-SPEnterpriseSearchServiceApplication
foreach ($ssa in $ssas) {
Write-Host -ForegroundColor Yellow
"Resuming the Search Service Application: $($ssa.DisplayName)"
Write-Host -ForegroundColor Yellow '
This could take a few minutes...'
Resume-SPEnterpriseSearchServiceApplication
-Identity $ssa | Out-Null
}
}
elseif ($pause -and $KeepSearchPaused -eq $true) {
Write-Host -ForegroundColor Yellow 'Not resuming the
Search Service Application(s)'
}
###Resuming IIS###
iisreset -start
$endTime = Get-Date
Write-Host -ForegroundColor Green 'Services are Started'
Write-Host
Write-Host
Write-Host -ForegroundColor Yellow ('Script completed in {0:g}' -f
($endTime - $startTime))
Write-Host -ForegroundColor Yellow 'Started:' $startTime
Write-Host -ForegroundColor Yellow 'Finished:' $endTime
if ($reboot) {
Write-Host -ForegroundColor Yellow 'A reboot is required'
}
}
I have discovered
that even with this fix, however, patching was still slow.
One issue, it turns
out was that the original script assumes that IISAdmin installed.
In the days of Windows Server 2012, you would include the IIS 6.0
Metabase Compatibility tools which included IISAdmin. You don't need that
anymore for SP SE.
Also, I noticed that
the w3svc service was often running still and have been manually stopping it
when CU installs have been taking too long.
I managed to
discover where the CU installation logs what it is doing:
While the CU is
installing, it is logged into: $env:temp\sts-x-none_MSPLOG.LOG
You can run to watch
what the install is doing live:
Get-Content
$env:temp\sts-x-none_MSPLOG.LOG -tail 500 -wait
One thing, I also
noticed is the log would eventually go into a loop trying to clean up files and
display a list of things preventing it from continuing:
Restart Manager Info: 3 entries
04/10/2024 19:19:48.026 [6900]: App[0]: (10748) Windows PowerShell (), type
= 5
04/10/2024 19:19:48.026 [6900]: App[1]: (6088) Windows PowerShell ISE (),
type = 0
04/10/2024 19:19:48.026 [6900]: App[2]: (10936) SharePoint Caching Service
(SPCache), type = 3
04/10/2024 19:19:48.026 [6900]: Security info:
04/10/2024 19:19:48.026 [6900]: Owner: S-1-5-18
04/10/2024 19:19:48.026 [6900]: Group: S-1-5-18
04/10/2024 19:19:48.026 [6900]: DACL information: 5 entries:
04/10/2024 19:19:48.026 [6900]: ACE[0]: Type = 0x00, Flags = 010, Mask =
001f01ff, SID = S-1-5-18
04/10/2024 19:19:48.026 [6900]: ACE[1]: Type = 0x00, Flags = 010, Mask =
001f01ff, SID = S-1-5-32-544
04/10/2024 19:19:48.026 [6900]: ACE[2]: Type = 0x00, Flags = 010, Mask =
001200a9, SID = S-1-5-32-545
04/10/2024 19:19:48.026 [6900]: ACE[3]: Type = 0x00, Flags = 010, Mask =
001200a9, SID = S-1-15-2-1
04/10/2024 19:19:48.026 [6900]: ACE[4]: Type = 0x00, Flags = 010, Mask =
001200a9, SID = S-1-15-2-2
04/10/2024 19:19:48.026 [6900]: Assembly Install: Failing
with hr=80070005 at RemoveDirectoryAndChildren, line 393
04/10/2024 19:19:48.026 [6900]: Detailed info about
C:\Windows\assembly\temp\JVPGGYWOGR\Microsoft.Office.InfoPath.dll
04/10/2024 19:19:48.042 [6900]: File attributes: 00000080
In this case, PowerShell and the SharePoint Cache service
were preventing it from continuing.
Another example here where IIS Worker Process may have been
preventing the clean up process from completing:
12/30/2022 00:29:50.842 [14812]: Detailed info about
C:\Windows\assembly\temp\KAITD5GHQO\Microsoft.SharePoint.IdentityModel.dll
12/30/2022 00:29:50.842 [14812]: File attributes: 00000080
12/30/2022 00:29:50.909 [14812]: Restart Manager Info: 4 entries
12/30/2022 00:29:50.909 [14812]: App[0]: (15072) IIS Worker
Process (), type = 5
12/30/2022 00:29:50.909 [14812]: App[1]: (548) Windows
PowerShell (), type = 5
12/30/2022 00:29:50.909 [14812]: App[2]: (13056) IIS Worker
Process (), type = 5
12/30/2022 00:29:50.909 [14812]: App[3]: (1684) IIS Worker
Process (), type = 5
12/30/2022 00:29:50.909 [14812]: Security info:
12/30/2022 00:29:50.909 [14812]: Owner: S-1-5-18
12/30/2022 00:29:50.909 [14812]: Group: S-1-5-18
12/30/2022 00:29:50.909 [14812]: DACL information: 5 entries:
12/30/2022 00:29:50.909 [14812]: ACE[0]: Type = 0x00, Flags =
010, Mask = 001f01ff, SID = S-1-5-18
12/30/2022 00:29:50.909 [14812]: ACE[1]: Type = 0x00, Flags =
010, Mask = 001f01ff, SID = S-1-5-32-544
12/30/2022 00:29:50.909 [14812]: ACE[2]: Type = 0x00, Flags =
010, Mask = 001200a9, SID = S-1-5-32-545
12/30/2022 00:29:50.909 [14812]: ACE[3]: Type = 0x00, Flags =
010, Mask = 001200a9, SID = S-1-15-2-1
12/30/2022 00:29:50.909 [14812]: ACE[4]: Type = 0x00, Flags =
010, Mask = 001200a9, SID = S-1-15-2-2
12/30/2022 00:29:50.909 [14812]: Assembly Install:
Failing with hr=80070005 at RemoveDirectoryAndChildren, line 393
If my understanding of these log entries is correct,
there is evidence that PowerShell, IIS, and some SharePoint Services may be
slowing down the CU install when it gets into this cleanup loop state.
So, it may be wise to not have some of those services or
apps running during the CU install to speed things up.
Therefore, rather than launching the update from
PowerShell and then leaving PowerShell open while waiting for the install to
complete as is done by the script, disable the SPTimerV4 job, stop IIS, and
stop the SPCache service if it is running on the computer. And consider closing PowerShell windows that
have the Microsoft.SharePoint.PowerShell PSSnapin added to it.
So, rather than a single module, maybe you could just use
a few ps1 scripts like so:
Pause-SPServicesForCU.ps1
Write-Host ("Adding Microsofot.SharePointPowerShell
Snapin...") -ForegroundColor Green;
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction Continue
#Display Current Services Running
Write-Host("Current SharePoint Service State: ");
$services = get-Service | where {$_.DisplayName.StartsWith("SharePoint")};
$services;
#Pause Search
$ssas = Get-SPEnterpriseSearchServiceApplication
foreach ($ssa in $ssas) {
if ($ssa.IsPaused() -eq 0)
{
Write-Host -ForegroundColor Yellow "Pausing the Search Service
Application: $($ssa.DisplayName)"
Write-Host
-ForegroundColor Yellow ' This could
take a few minutes...'
Suspend-SPEnterpriseSearchServiceApplication -Identity $ssa | Out-Null
}
else
{
Write-Host("Search is paused, alrady.") -ForegroundColor Green;
}
}
#Stop IISAdmin
$iisadminsvc = Get-Service -Name IISADMIN;
if ($iisadminsvc -ne $null)
{
Set-Service -Name IISADMIN -StartupType Disabled;
}
else
{
Write-Host("No IISAdmin Service on this system. This is not an issue for IIS10...") -ForegroundColor Yellow;
}
Write-Host -ForegroundColor Green 'Gracefully stopping IIS...'
Write-Host
iisreset /stop /noforce
$w3svc = Get-Service -Name W3SVC
if ($w3svc -ne $null)
{
Stop-Service -Name W3SVC;
}
$w3svc
Write-Host("Disabling the SPTimerV4 service....") -ForegroundColor Green;
#Stop SPTimerV4
$sptimerv4 = Get-Service -Name SPTimerV4;
if ($sptimerv4 -ne $null)
{
Set-Service -Name SPTimerV4 -StartupType Disabled;
Stop-Service -Name SPTimerV4 -WA 0;
}
$sptimerv4 = Get-Service -Name SPTimerV4;
$sptimerv4
#Stop Other SharePoint Services
Write-Host ("Stopping other SharePoint Services...") -ForegroundColor Green;
$services = get-Service | where {$_.DisplayName.StartsWith("SharePoint")};
$services
foreach ($service in $services)
{
#Stop the SP Cache service
if ($service.Status -eq "Running" -and $service.Name -eq "SPCache")
{
Write-Host("Stopping " + $service.Name + "....") -ForegroundColor Green;
Stop-Service -Name $service.Name;
}
}
$services = get-Service | where {$_.DisplayName.StartsWith("SharePoint")};
$services;
Write-Host("Ready to launch the SP CU. You can close this Powershell afer launching,
but remember to run Start-SPServicesAfterCU.") -ForegroundColor Green;
Write-Host("To view CU install details:");
Write-Host("Get-Content $env:temp\sts-x-none_MSPLOG.LOG -tail 500 -wait") -ForegroundColor Green;
After pausing
services, you would manually launch the CU.
Start-SPServicesAfterCU.ps1
Write-Host ("Adding Microsofot.SharePointPowerShell
Snapin...") -ForegroundColor Green;
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction Continue
#Stop IISAdmin
$iisadminsvc = Get-Service -Name IISADMIN;
if ($iisadminsvc -ne $null)
{
Set-Service -Name IISADMIN -StartupType Automatic;
}
else
{
Write-Host("No IISAdmin Service on this system. This is not an issue for IIS10...") -ForegroundColor Yellow;
}
Write-Host -ForegroundColor Green 'Starting IIS...'
Write-Host
iisreset /start
$w3svc = Get-Service -Name W3SVC
if ($w3svc -ne $null -and $w3svc.Status -eq "Stopped")
{
Start-Service -Name W3SVC;
$w3svc = Get-Service -Name W3SVC;
}
$w3svc
Write-Host("Enabling SPTimerV4...") -ForegroundColor Green;
#Enable SPTimerV4
$sptimerv4 = Get-Service -Name SPTimerV4;
if ($sptimerv4 -ne $null)
{
Set-Service -Name SPTimerV4 -StartupType Automatic;
Start-Service -Name SPTimerV4;
}
$sptimerv4 = Get-Service -Name SPTimerV4;
$sptimerv4
Write-Host("Now that the SPTimerV4 service is running, timer
jobs should start up dependent SPServices based on the role of the server. Verify just in case.");
$services = get-Service | where {$_.DisplayName.StartsWith("SharePoint")};
$services;
Write-Host("Next Things to do are Invoke-SPConfigWizard and
Resume-SPSearch") -ForegroundColor Green;
After installing the CU on all
SP Servers:
Invoke-SPConfigWizard.ps1
PSConfig.exe -cmd upgrade -inplace b2b -wait -cmd applicationcontent -install -cmd installfeatures -cmd secureresources -cmd services -install
Resume search after patching is
complete:
Resume-SPSearch
#Resume Search
$ssas = Get-SPEnterpriseSearchServiceApplication
foreach ($ssa in $ssas) {
if ($ssa.IsPaused() -ne 0)
{
Write-Host -ForegroundColor Yellow "Resuming the Search Service
Application: $($ssa.DisplayName)"
Write-Host
-ForegroundColor Yellow ' This could
take a few minutes...'
Resume-SPEnterpriseSearchServiceApplication -Identity $ssa
}
else
{
Write-Host("Search is resumed, already.") -ForegroundColor Green;
}
}
Comments
Post a Comment