UpdateOS icon indicating copy to clipboard operation
UpdateOS copied to clipboard

Feature Update issue

Open hacklhar opened this issue 1 year ago • 5 comments

Hi Michael,

it seems the latest feature update to 24h2 will be downloaded which stuck the update process during Autopilot. Did try some exclusion options but no one was working.

Maybe you´ve an idea to implement a workaround. UpdateOS.log

thx & regards, Harald

hacklhar avatar Oct 21 '24 05:10 hacklhar

if we add following entry - if ($.Title -notmatch "24H2") { [void]$WUUpdates.Add($) } the 24h2 update is not getting downloaded, but also the latest CU from current month not

hacklhar avatar Oct 21 '24 07:10 hacklhar

One way of solving it may be to use the 1.6 version of the script which included the PS Modules, and use the hide option IE:

Opt into Microsoft Update

Add-WUServiceManager -ServiceID "7971f918-a847-4430-9279-4a52d1efe18d" -AddServiceFlag 7 -Confirm:$False

Install all available updates

$ts = get-date -f "yyyy/MM/dd hh:mm:ss tt" Write-Host "$ts Installing updates."

#Hide 24H2 KB hidelist format "kbxxx","kbxxx" $HideList="KB5044284" Get-Windowsupdate -KBArticleID $hidelist -Hide -AcceptAll

Install-WindowsUpdate -NotTitle "preview" -AcceptAll -IgnoreReboot -Verbose | Select Title, KB, Result | Format-Table $needReboot = (Get-WURebootStatus -Silent).RebootRequired


Instead of the hidelist, you may also just include the -NotKBArticleID variable in install-windowsupdate. Like:
Install-WindowsUpdate -NotKBArticleID KB5044284 -NotTitle "preview" -AcceptAll -IgnoreReboot -Verbose | Select Title, KB, Result | Format-Table $needReboot = (Get-WURebootStatus -Silent).RebootRequired

I'm not experienced in Powershell, but it worked for us at least.

JanVidarA avatar Oct 28 '24 15:10 JanVidarA

@JanVidarA we already tried several variations - if we add -NotKBArticleID KB5044284 -NotTitle "preview" we only get updates for Defender and not the latest CU. Btw KB5044284 ist not the "Windows 11, version 24H2" upgrade

hacklhar avatar Oct 29 '24 08:10 hacklhar

@hacklhar, this is the v1.6 script I'm using. It installs "everything" except for the 2024-10 update KB5044285, and some minor defender updates which comes afterwards. I'm satisfied with that, as it doesn't affect user too much. There's an option to install specific KBs also, although I haven't tried it myself.

https://powershellisfun.com/2024/01/19/using-the-powershell-pswindowsupdate-module/

says something about that. Adding

Install-WindowsUpdate -KBArticleID KB5044285

Might solve it. I don't know. That's all I got :-)

Install command for win32 app: powershell.exe -noprofile -executionpolicy bypass -file .\UpdateOS.ps1 -Reboot Hard

...

<#PSScriptInfo

.VERSION 1.6

.GUID 07e4ef9f-8341-4dc4-bc73-fc277eb6b4e6

.AUTHOR Michael Niehaus

.COMPANYNAME Microsoft

.COPYRIGHT

.TAGS Windows AutoPilot Update OS

.LICENSEURI

.PROJECTURI

.ICONURI

.EXTERNALMODULEDEPENDENCIES

.REQUIREDSCRIPTS

.EXTERNALSCRIPTDEPENDENCIES

.RELEASENOTES Version 1.6: Default to soft reboot. Version 1.5: Improved logging, reboot logic. Version 1.4: Fixed reboot logic. Version 1.3: Force use of Microsoft Update/WU. Version 1.2: Updated to work on ARM64. Version 1.1: Cleaned up output. Version 1.0: Original published version.

#>

<# .SYNOPSIS Installs the latest Windows 10/11 quality updates. .DESCRIPTION This script uses the PSWindowsUpdate module to install the latest cumulative update for Windows 10/11. .EXAMPLE .\UpdateOS.ps1 #>

[CmdletBinding()] Param( [Parameter(Mandatory=$False)] [ValidateSet('Soft', 'Hard', 'None', 'Delayed')] [String] $Reboot = 'Soft', [Parameter(Mandatory=$False)] [Int32] $RebootTimeout = 120 )

Process {

If we are running as a 32-bit process on an x64 system, re-launch as a 64-bit process

if ("$env:PROCESSOR_ARCHITEW6432" -ne "ARM64") { if (Test-Path "$($env:WINDIR)\SysNative\WindowsPowerShell\v1.0\powershell.exe") { & "$($env:WINDIR)\SysNative\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy bypass -NoProfile -File "$PSCommandPath" -Reboot $Reboot -RebootTimeout $RebootTimeout Exit $lastexitcode } }

Create a tag file just so Intune knows this was installed

if (-not (Test-Path "$($env:ProgramData)\Microsoft\UpdateOS")) { Mkdir "$($env:ProgramData)\Microsoft\UpdateOS" } Set-Content -Path "$($env:ProgramData)\Microsoft\UpdateOS\UpdateOS.ps1.tag" -Value "Installed"

Start logging

Start-Transcript "$($env:ProgramData)\Microsoft\UpdateOS\UpdateOS.log"

Main logic

$needReboot = $false

Load module from PowerShell Gallery

$ts = get-date -f "yyyy/MM/dd hh:mm:ss tt" Write-Host "$ts Importing NuGet and PSWindowsUpdate" $null = Install-PackageProvider -Name NuGet -Force $null = Install-Module PSWindowsUpdate -Force Import-Module PSWindowsUpdate

Opt into Microsoft Update

Add-WUServiceManager -ServiceID "7971f918-a847-4430-9279-4a52d1efe18d" -AddServiceFlag 7 -Confirm:$False

Install all available updates

$ts = get-date -f "yyyy/MM/dd hh:mm:ss tt" Write-Host "$ts Installing updates."

#Hide 24H2 KB hidelist format "kbxxx","kbxxx" $HideList="KB5044284" Get-Windowsupdate -KBArticleID $hidelist -Hide -AcceptAll

Install-WindowsUpdate -NotTitle "preview" -AcceptAll -IgnoreReboot -Verbose | Select Title, KB, Result | Format-Table $needReboot = (Get-WURebootStatus -Silent).RebootRequired

Specify return code

$ts = get-date -f "yyyy/MM/dd hh:mm:ss tt" if ($needReboot) { Write-Host "$ts Windows Update indicated that a reboot is needed." } else { Write-Host "$ts Windows Update indicated that no reboot is required." }

For whatever reason, the reboot needed flag is not always being properly set. So we always want to force a reboot.

If this script (as an app) is being used as a dependent app, then a hard reboot is needed to get the "main" app to

install.

$ts = get-date -f "yyyy/MM/dd hh:mm:ss tt" if ($Reboot -eq "Hard") { Write-Host "$ts Exiting with return code 1641 to indicate a hard reboot is needed." Stop-Transcript Exit 1641 } elseif ($Reboot -eq "Soft") { Write-Host "$ts Exiting with return code 3010 to indicate a soft reboot is needed." Stop-Transcript Exit 3010 } elseif ($Reboot -eq "Delayed") { Write-Host "$ts Rebooting with a $RebootTimeout second delay" & shutdown.exe /r /t $RebootTimeout /c "Rebooting to complete the installation of Windows updates." Exit 0 } else { Write-Host "$ts Skipping reboot based on Reboot parameter (None)" Exit 0 }

}

JanVidarA avatar Oct 29 '24 08:10 JanVidarA

@JanVidarA thanks for providing your version of ps, but it still is not loading the latest CU for 23H2. No clue what´s going wrong

hacklhar avatar Oct 29 '24 09:10 hacklhar

@mtniehaus do you have any suggestions to prevent the Feature Update 24H2 from being installed which gets us stuck in ESP?

hillihappo avatar Jan 08 '25 08:01 hillihappo

on version 1.10, I changed the part that sets the criteria to avoid titles containing "24H2" to avoid update to 24h2.

$WUUpdates = New-Object -ComObject Microsoft.Update.UpdateColl $ts = get-date -f "yyyy/MM/dd hh:mm:ss tt" Write-Host "$ts Getting $_ updates."
((New-Object -ComObject Microsoft.Update.Session).CreateupdateSearcher().Search($)).Updates | ForEach-Object { if (!$.EulaAccepted) { $.AcceptEula() } if ($.Title -notmatch "Preview" -and $.Title -notmatch "24H2")
{ [void]$WUUpdates.Add($
) }

JanVidarA avatar Jan 08 '25 08:01 JanVidarA

So you guys experienced the tool doing feature upgrades? Regarding this issue, https://github.com/mtniehaus/UpdateOS/issues/9, it should never do feature upgrades. Thank you for clarification.

swissbuechi avatar Jan 09 '25 07:01 swissbuechi

@swissbuechi we encounter issues that we get the feature update for 24H2 offered each time we are running UpdateOS

hacklhar avatar Jan 09 '25 08:01 hacklhar

@swissbuechi we encounter issues that we get the feature update for 24H2 offered each time we are running UpdateOS

@hacklhar Thank you for clarification. I have the requirement to completely disable the installation of any feature upgrades. I'll try to implement this and report it back here if I succeed.

swissbuechi avatar Jan 09 '25 10:01 swissbuechi

@swissbuechi

By filtering on CategoryID you can block Feature Updates (Feature Updates use CategoryID 3689BDC8-B205-4AF4-8D4A-A63924C5E9D5). I think this is a cleaner approach than trying to filter on title. The below snippet fixes issue #9.

I do not have experience working with COM objects, so there is likely a much more optimized way to do this. Some updates may be a member of multiple categories, so I have included logic to account for that. This snippet additionally includes a logic check for the 'EulaAccepted' property as requested in issue #12.

$queries | ForEach-Object {

    $WUUpdates = New-Object -ComObject Microsoft.Update.UpdateColl
    $TimeStamp = get-date -f "yyyy/MM/dd hh:mm:ss tt"
    Write-Host "$TimeStamp Getting $_ updates."        
    $CandidateUpdates = ((New-Object -ComObject Microsoft.Update.Session).CreateupdateSearcher().Search($_)).Updates 
    ForEach ($CandidateUpdate in $CandidateUpdates) {
        If ($CandidateUpdate.Title -notmatch "Preview") {
            If ($CandidateUpdate | Get-Member EulaAccepted) { if (!$CandidateUpdate.EulaAccepted) { $CandidateUpdate.AcceptEula() } }
            ForEach ($CandidateUpdateCategory in $CandidateUpdate.Categories) {
              if ($CandidateUpdateCategory.CategoryID -ne "3689BDC8-B205-4AF4-8D4A-A63924C5E9D5" -and $CandidateUpdate -notin $WUUpdates) { [void]$WUUpdates.Add($CandidateUpdate) }
            }
        }
    }

agryphtel avatar Jan 13 '25 15:01 agryphtel

I've added logic to do this in version 2.1.

mtniehaus avatar May 28 '25 09:05 mtniehaus