Skip to content

Commit

Permalink
New script for updating Windows
Browse files Browse the repository at this point in the history
The existing Windows Update script is failing to run on Windows 24H2 due to deprecation within the Windows Update Agent API. This necessitates the development of a new script compatible with the updated API.
  • Loading branch information
Pablo Herranz Ramírez committed Jan 31, 2025
1 parent e8daacc commit c2ff764
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 23 deletions.
91 changes: 91 additions & 0 deletions data/wsl/UpdateInstall.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Define a function to log messages with timestamps
function LogMessage {
param (
[string]$Message,
[string]$Color = "White"
)
$Timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
Write-Host "$Timestamp - $Message" -ForegroundColor $Color
}

# Validate COM port status at script start
if (-not $port -or -not ($port -is [System.IO.Ports.SerialPort]) -or -not $port.IsOpen) {
LogMessage "COM port is not initialized or closed. Exiting." -Color "Red"
exit 1
}

# Start logging
LogMessage "Starting Windows Update process..."

# Create Update Session
$Session = New-Object -ComObject Microsoft.Update.Session
$Searcher = $Session.CreateUpdateSearcher()

# Search for Updates
LogMessage "Searching for updates..."
$SearchResult = $Searcher.Search("IsInstalled=0")

# Check if updates are available
if ($SearchResult.Updates.Count -eq 0) {
LogMessage "System already up-to-date" -Color "Green"
$port.WriteLine('0')
exit 0
}

# Display updates found
LogMessage "$($SearchResult.Updates.Count) update(s) found."
$UpdatesToInstall = New-Object -ComObject Microsoft.Update.UpdateColl
foreach ($Update in $SearchResult.Updates) {
LogMessage "Update found: $($Update.Title)"
$UpdatesToInstall.Add($Update) | Out-Null
}

# Process updates one by one (download + install)
foreach ($Update in $SearchResult.Updates) {
LogMessage "Processing: $($Update.Title)" -Color "Cyan"

# Download the update
try {
LogMessage "Downloading $($Update.Title)..."
$Downloader = $Session.CreateUpdateDownloader()
$SingleUpdateColl = New-Object -ComObject Microsoft.Update.UpdateColl
$SingleUpdateColl.Add($Update) | Out-Null
$Downloader.Updates = $SingleUpdateColl
$DownloadResult = $Downloader.Download()

if ($DownloadResult.ResultCode -ne 2) {
LogMessage "Download failed (Result code: $($DownloadResult.ResultCode))"
$port.WriteLine('1')
exit 1
}
LogMessage "Downloaded successfully." -Color "Green"
} catch {
LogMessage "ERROR downloading $($Update.Title): $_" -Color "Red"
$port.WriteLine('1')
exit 1
}

# Install the update
try {
LogMessage "Installing $($Update.Title)..."
$Installer = $Session.CreateUpdateInstaller()
$Installer.Updates = $SingleUpdateColl
$InstallResult = $Installer.Install()

if ($InstallResult.ResultCode -ne 2) {
LogMessage "Installation failed (Result code: $($InstallResult.ResultCode))"
$port.WriteLine('1')
exit 1
}
LogMessage "Installed successfully." -Color "Green"
} catch {
LogMessage "ERROR installing $($Update.Title): $_" -Color "Red"
$port.WriteLine('1')
exit 1
}
}

# Completion message
LogMessage "Windows Update process completed."
$port.WriteLine('0')
exit 0
43 changes: 25 additions & 18 deletions lib/windowsbasetest.pm
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ sub wait_boot_windows {

# Reset the consoles: there is no user logged in anywhere
reset_consoles;
assert_screen 'windows-screensaver', 900;
# Installation process has become slower since 24H2
assert_screen 'windows-screensaver', 3600;
send_key_until_needlematch 'windows-login', 'esc';
type_password;
send_key 'ret';
Expand All @@ -141,38 +142,27 @@ sub wait_boot_windows {
wait_still_screen stilltime => 60, timeout => 300;
# When starting Windows for the first time, several screens or pop-ups may appear
# in a different order. We'll try to handle them until the desktop is shown
assert_screen(['windows-desktop', 'windows-edge-decline', 'networks-popup-be-discoverable', 'windows-start-menu', 'windows-qemu-drivers'], timeout => 120);
assert_screen(['windows-edge-welcome', 'windows-desktop', 'windows-edge-decline', 'networks-popup-be-discoverable', 'windows-start-menu', 'windows-qemu-drivers', 'windows-setup-browser'], timeout => 120);
while (not match_has_tag('windows-desktop')) {
assert_and_click 'windows-edge-welcome' if (match_has_tag 'windows-edge-welcome');
assert_and_click 'windows-setup-browser' if (match_has_tag 'windows-setup-browser');
assert_and_click 'network-discover-yes' if (match_has_tag 'networks-popup-be-discoverable');
assert_and_click 'windows-edge-decline' if (match_has_tag 'windows-edge-decline');
assert_and_click 'windows-start-menu' if (match_has_tag 'windows-start-menu');
assert_and_click 'windows-qemu-drivers' if (match_has_tag 'windows-qemu-drivers');
wait_still_screen stilltime => 15, timeout => 60;
assert_screen(['windows-desktop', 'windows-edge-decline', 'networks-popup-be-discoverable', 'windows-start-menu', 'windows-qemu-drivers'], timeout => 120);
assert_screen(['windows-edge-welcome', 'windows-desktop', 'windows-edge-decline', 'networks-popup-be-discoverable', 'windows-start-menu', 'windows-qemu-drivers', 'windows-setup-browser'], timeout => 120);
}

# TODO: all this part should be added to the unattend XML in the future

# Setup stable lock screen background
record_info('Config lockscreen', 'Setup stable lock screen background');
$self->use_search_feature('lock screen settings');
assert_screen 'windows-lock-screen-in-search';
wait_still_screen stilltime => 2, timeout => 10, similarity_level => 43;
assert_and_click 'windows-lock-screen-in-search', dclick => 1;
assert_screen 'windows-lock-screen-settings';
assert_and_click 'windows-lock-screen-background';
assert_and_click 'windows-select-picture';
assert_and_click 'windows-close-lockscreen';
wait_still_screen stilltime => 2, timeout => 10, similarity_level => 43;
# Windows 11 24H2 does not allow to change the lockscreen unless activated
$self->set_stable_lockscreen unless check_var('VERSION', '11');

# These commands disable notifications that Windows shows randomly and
# make our windows lose focus
$self->open_powershell_as_admin;
$self->run_in_powershell(cmd => 'reg add "HKLM\Software\Policies\Microsoft\Windows" /v Explorer');
$self->run_in_powershell(cmd => 'reg add "HKLM\Software\Policies\Microsoft\Windows\Explorer" /v DisableNotificationCenter /t REG_DWORD /d 1');
$self->run_in_powershell(cmd => 'reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\PushNotifications" /v ToastEnabled /t REG_DWORD /d 0');
# Prevent password from expiring:
$self->run_in_powershell(cmd => 'wmic UserAccount set PasswordExpires=False');
record_info 'Port close', 'Closing serial port...';
$self->run_in_powershell(cmd => '$port.close()', code => sub { });
$self->run_in_powershell(cmd => 'exit', code => sub { });
Expand Down Expand Up @@ -245,4 +235,21 @@ sub power_configuration {
);
}

sub set_stable_lockscreen {
my $self = shift;

# TODO: all this part should be added to the unattend XML in the future
# Setup stable lock screen background
record_info('Config lockscreen', 'Setup stable lock screen background');
$self->use_search_feature('lock screen settings');
assert_screen 'windows-lock-screen-in-search';
wait_still_screen stilltime => 2, timeout => 10, similarity_level => 43;
assert_and_click 'windows-lock-screen-in-search', dclick => 1;
assert_screen 'windows-lock-screen-settings';
assert_and_click 'windows-lock-screen-background';
assert_and_click 'windows-select-picture';
assert_and_click 'windows-close-lockscreen';
wait_still_screen stilltime => 2, timeout => 10, similarity_level => 43;
}

1;
2 changes: 1 addition & 1 deletion schedule/wsl/install/create_windows_image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ conditional_schedule:
schedule:
- wsl/install/ms_win_installation
- '{{unattended_install}}'
- wsl/update_windows
- wsl/install/update_windows
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ use testapi;
sub run {
my $self = shift;

my $vbs_url = data_url("wsl/UpdateInstall.vbs");
my $vbs_url = data_url("wsl/UpdateInstall.ps1");
$self->open_powershell_as_admin;
$self->run_in_powershell(cmd => "Invoke-WebRequest -Uri \"$vbs_url\" -OutFile \"C:\\UpdateInstall.vbs\"");
$self->run_in_powershell(cmd => "Invoke-WebRequest -Uri \"$vbs_url\" -OutFile \"\$env:TEMP\\UpdateInstall.ps1\"");
$self->run_in_powershell(cmd => "Set-ExecutionPolicy Bypass -Scope CurrentUser -Force");
$self->run_in_powershell(
cmd => 'cd \\; $port.WriteLine($(cscript .\\UpdateInstall.vbs /Automate))',
cmd => "cd \$env:TEMP; .\\UpdateInstall.ps1",
code => sub {
die("Update script finished unespectedly or timed out...")
unless wait_serial("The update process finished with value 1", timeout => 3600);
unless wait_serial('0', timeout => 3600);
}
);
save_screenshot;
Expand Down

0 comments on commit c2ff764

Please sign in to comment.