From df27520b1f223f23188191ec1a3fdce76f5cddd8 Mon Sep 17 00:00:00 2001 From: Aleksandr Chebotov <47745270+al-cheb@users.noreply.github.com> Date: Tue, 16 Nov 2021 17:14:17 +0300 Subject: [PATCH] [Windows] Add test to validate windows updates installation (#4489) * Add test to validate windows updates installation * Add function Get-WindowsUpdatesHistory --- .../scripts/ImageHelpers/ImageHelpers.psm1 | 1 + .../scripts/ImageHelpers/InstallHelpers.ps1 | 44 +++++++++++++++++++ .../Installers/Install-WindowsUpdates.ps1 | 33 +++++++++++++- .../scripts/Tests/WindowsFeatures.Tests.ps1 | 22 ++++++++++ images/win/windows2019.json | 28 +++++------- 5 files changed, 110 insertions(+), 18 deletions(-) diff --git a/images/win/scripts/ImageHelpers/ImageHelpers.psm1 b/images/win/scripts/ImageHelpers/ImageHelpers.psm1 index 5beeef1f..09e4962a 100644 --- a/images/win/scripts/ImageHelpers/ImageHelpers.psm1 +++ b/images/win/scripts/ImageHelpers/ImageHelpers.psm1 @@ -43,4 +43,5 @@ Export-ModuleMember -Function @( 'Get-AndroidPackagesByVersion' 'Get-VisualStudioInstance' 'Get-VisualStudioComponents' + 'Get-WindowsUpdatesHistory' ) diff --git a/images/win/scripts/ImageHelpers/InstallHelpers.ps1 b/images/win/scripts/ImageHelpers/InstallHelpers.ps1 index e05e44e9..0791b7f3 100644 --- a/images/win/scripts/ImageHelpers/InstallHelpers.ps1 +++ b/images/win/scripts/ImageHelpers/InstallHelpers.ps1 @@ -489,3 +489,47 @@ function Get-AndroidPackagesByVersion { $packagesByVersion = $packagesByName | Where-Object { ($_.Split($Delimiter)[$Index] -as $Type) -ge $MinimumVersion } return $packagesByVersion | Sort-Object { $_.Split($Delimiter)[$Index] -as $Type} -Unique } + +function Get-WindowsUpdatesHistory { + $allEvents = @{} + # 19 - Installation Successful: Windows successfully installed the following update + # 20 - Installation Failure: Windows failed to install the following update with error + # 43 - Installation Started: Windows has started installing the following update + $filter = @{ + LogName = "System" + Id = 19, 20, 43 + ProviderName = "Microsoft-Windows-WindowsUpdateClient" + } + $events = Get-WinEvent -FilterHashtable $filter -ErrorAction SilentlyContinue | Sort-Object Id + + foreach ( $event in $events ) { + switch ( $event.Id ) { + 19 { + $status = "Successful" + $title = $event.Properties[0].Value + $allEvents[$title] = "" + break + } + 20 { + $status = "Failure" + $title = $event.Properties[1].Value + $allEvents[$title] = "" + break + } + 43 { + $status = "InProgress" + $title = $event.Properties[0].Value + break + } + } + + if ( $status -eq "InProgress" -and $allEvents.ContainsKey($title) ) { + continue + } + + [PSCustomObject]@{ + Status = $status + Title = $title + } + } +} diff --git a/images/win/scripts/Installers/Install-WindowsUpdates.ps1 b/images/win/scripts/Installers/Install-WindowsUpdates.ps1 index eb19a3ea..29960409 100644 --- a/images/win/scripts/Installers/Install-WindowsUpdates.ps1 +++ b/images/win/scripts/Installers/Install-WindowsUpdates.ps1 @@ -4,5 +4,34 @@ ## Should be run at end, just before SoftwareReport and Finalize-VM.ps1. ################################################################################ -Write-Host "Run windows updates" -Get-WUInstall -MicrosoftUpdate -AcceptAll -Install -IgnoreUserInput -IgnoreReboot +function Install-WindowsUpdates { + Write-Host "Starting wuauserv" + Start-Service -Name wuauserv -PassThru | Out-Host + + Write-Host "Getting list of available windows updates" + Get-WindowsUpdate -MicrosoftUpdate -OutVariable updates | Out-Host + + if ( -not $updates ) { + Write-Host "There are no windows updates to install" + return + } + + Write-Host "Installing windows updates" + Get-WindowsUpdate -MicrosoftUpdate -AcceptAll -Install -IgnoreUserInput -IgnoreReboot | Out-Host + + Write-Host "Validating windows updates installation and skip Microsoft Defender Antivirus" + # Azure service can automatic updates AV engine(Microsoft.Azure.Security.AntimalwareSignature.AntimalwareConfiguration) + # Get-WUHistory doesn't support Windows Server 2022 + $wuHistory = Get-WindowsUpdatesHistory | Where-Object { $_.Status -in ("Successful", "InProgress") } + $wuFail = $updates[0] | Where-Object Title -notmatch "Microsoft Defender Antivirus" | Where-Object { -not ($wuHistory.Title -match $_.KB) } + + if ( $wuFail ) { + Write-Host "Windows updates failed to install: $($wuFail.KB)" + exit 1 + } +} + +Install-WindowsUpdates + +# Create complete windows update file +New-Item -Path $env:windir -Name WindowsUpdateDone.txt -ItemType File | Out-Null diff --git a/images/win/scripts/Tests/WindowsFeatures.Tests.ps1 b/images/win/scripts/Tests/WindowsFeatures.Tests.ps1 index f2a591ac..7c754967 100644 --- a/images/win/scripts/Tests/WindowsFeatures.Tests.ps1 +++ b/images/win/scripts/Tests/WindowsFeatures.Tests.ps1 @@ -56,3 +56,25 @@ Describe "Test Signed Drivers" -Skip:(Test-IsWin16) { "$(bcdedit)" | Should -Match "testsigning\s+Yes" } } + +Describe "Windows Updates" { + It "WindowsUpdateDone.txt should exist" { + "$env:windir\WindowsUpdateDone.txt" | Should -Exist + } + + $testCases = Get-WindowsUpdatesHistory | Sort-Object Title | ForEach-Object { + @{ + Title = $_.Title + Status = $_.Status + } + } + + It "