diff --git a/config/tweaks.json b/config/tweaks.json
index 27c7f3b5..4c1fd600 100644
--- a/config/tweaks.json
+++ b/config/tweaks.json
@@ -2382,13 +2382,7 @@
Set-ItemProperty -Path \"HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SystemRestore\" -Name \"SystemRestorePointCreationFrequency\" -Value \"0\" -Type DWord -Force -ErrorAction Stop | Out-Null
}
- # Attempt to load the required module for Get-ComputerRestorePoint
- try {
- Import-Module Microsoft.PowerShell.Management -ErrorAction Stop
- } catch {
- Write-Host \"Failed to load the Microsoft.PowerShell.Management module: $_\"
- return
- }
+ Invoke-WinUtilInitializeModule -module \"Microsoft.PowerShell.Management\"
# Get all the restore points for the current day
try {
diff --git a/functions/public/Invoke-WPFButton.ps1 b/functions/public/Invoke-WPFButton.ps1
index b90c63d3..9d17b713 100644
--- a/functions/public/Invoke-WPFButton.ps1
+++ b/functions/public/Invoke-WPFButton.ps1
@@ -62,5 +62,10 @@ function Invoke-WPFButton {
"WPFWinUtilInstallPSProfile" {Invoke-WinUtilInstallPSProfile}
"WPFWinUtilUninstallPSProfile" {Invoke-WinUtilUninstallPSProfile}
"WPFWinUtilSSHServer" {Invoke-WPFSSHServer}
+ "WPFScanUpdates" {Invoke-WPFUpdateScan -type "updates"}
+ "WPFShowUpdateHistory" { Invoke-WPFUpdateHistoryToggle }
+ "WPFUpdateSelectedInstall" {Invoke-WPFUpdateMGMT -Selected}
+ "WPFUpdateAllInstall" {Invoke-WPFUpdateMGMT -All}
+ "WPFUpdateScanHistory" {Invoke-WPFUpdateScan -type "history"}
}
}
diff --git a/functions/public/Invoke-WPFUpdateMGMT.ps1 b/functions/public/Invoke-WPFUpdateMGMT.ps1
new file mode 100644
index 00000000..f3ba25b7
--- /dev/null
+++ b/functions/public/Invoke-WPFUpdateMGMT.ps1
@@ -0,0 +1,127 @@
+
+function Invoke-WinUtilUpdateInstall {
+
+ <#
+ .SYNOPSIS
+ Installs Windows updates using the Initialize-WindowsUpdateModule and Install-WindowsUpdate cmdlets.
+
+ .PARAMETER Params
+ A hashtable containing the parameters for the Install-WindowsUpdate cmdlet.
+
+ #>
+
+ param (
+ [Parameter(Mandatory=$true)]
+ [hashtable]$Params
+ )
+
+ try {
+ Initialize-WindowsUpdateModule
+ Install-WindowsUpdate @Params
+ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
+ }
+ catch {
+ Write-Host "Error installing updates: $_" -ForegroundColor Red
+ Set-WinUtilTaskbaritem -state "Error" -overlay "warning"
+ }
+}
+
+function Invoke-WPFUpdateMGMT {
+
+ <#
+ .SYNOPSIS
+ Manages Windows Update Installation
+
+ .PARAMETER Selected
+ A switch parameter that indicates whether to install only selected updates.
+
+ .PARAMETER All
+ A switch parameter that indicates whether to install all available updates.
+
+ #>
+
+ param (
+ [switch]$Selected,
+ [switch]$All
+ )
+
+ # Prepare common installation parameters
+ $params = @{
+ Confirm = $false
+ IgnoreReboot = $true
+ IgnoreRebootRequired = $true
+ }
+
+ if ($sync["WPFUpdateVerbose"].IsChecked) {
+ $params['Verbose'] = $true
+ }
+
+ try {
+ if ($All) {
+ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo"
+ Invoke-WinUtilUpdateControls -state $false
+ Invoke-WPFRunspace -ArgumentList $params -DebugPreference $DebugPreference -ScriptBlock {
+ param ($params)
+
+ try {
+ Write-Host "Installing all available updates..."
+ Invoke-WinUtilUpdateInstall -Params $params
+ Write-Host "All available updates installed successfully"
+ $sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
+ } catch {
+ Write-Host "Error installing updates: $_" -ForegroundColor Red
+ $sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "Error" -overlay "warning" })
+ }
+ }
+ Invoke-WinUtilUpdateControls -state $true
+ } elseif ($Selected -and $sync["WPFUpdatesList"].SelectedItems.Count -gt 0) {
+ Write-Host "Installing selected updates..."
+
+ # Get selected updates
+ $selectedUpdates = $sync["WPFUpdatesList"].SelectedItems | ForEach-Object {
+ [PSCustomObject]@{
+ ComputerName = $_.ComputerName
+ Title = $_.LongTitle
+ KB = $_.KB
+ }
+ }
+
+ # Install selected updates
+ Invoke-WPFRunspace -ParameterList @(("selectedUpdates", $selectedUpdates),("params", $params)) -DebugPreference $DebugPreference -ScriptBlock {
+ param ($selectedUpdates, $params)
+
+ $sync.form.Dispatcher.Invoke([action] {
+ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo"
+ Invoke-WinUtilUpdateControls -state $false
+ })
+
+ foreach ($update in $selectedUpdates) {
+ Write-Host "Installing update $($update.Title) on $($update.ComputerName)"
+
+ # Prepare update-specific parameters
+ $updateParams = $params.Clone()
+ $updateParams['ComputerName'] = $update.ComputerName
+
+ # Install update based on KB or Title
+ if ($update.KB) {
+ Get-WindowsUpdate -KBArticleID $update.KB -Install @updateParams
+ } else {
+ Get-WindowsUpdate -Title $update.Title -Install @updateParams
+ }
+ }
+
+ $sync.form.Dispatcher.Invoke([action] {
+ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
+ Invoke-WinUtilUpdateControls -state $true
+ })
+ Write-Host "Selected updates installed successfully"
+ }
+ } else {
+ Write-Host "No updates selected"
+ }
+
+ } catch {
+ Write-Host "Error installing updates: $_" -ForegroundColor Red
+ Set-WinUtilTaskbaritem -state "Error" -overlay "warning"
+ }
+}
diff --git a/functions/public/Invoke-WPFUpdateScan.ps1 b/functions/public/Invoke-WPFUpdateScan.ps1
new file mode 100644
index 00000000..3e3e538b
--- /dev/null
+++ b/functions/public/Invoke-WPFUpdateScan.ps1
@@ -0,0 +1,122 @@
+function Invoke-WPFUpdateHistoryToggle {
+ <#
+ .SYNOPSIS
+ Toggles the visibility of the Windows update history and available updates.
+ #>
+
+ $showHistory = $sync["WPFShowUpdateHistory"].Content -eq "Show History"
+
+ $sync["WPFShowUpdateHistory"].Content = if ($showHistory) { "Show available Updates" } else { "Show History" }
+ $sync["HistoryGrid"].Visibility = if ($showHistory) { "Visible" } else { "Collapsed" }
+ $sync["UpdatesGrid"].Visibility = if ($showHistory) { "Collapsed" } else { "Visible" }
+}
+
+function Invoke-WinUtilUpdateControls {
+ <#
+ .SYNOPSIS
+ Disables or enables the update controls based on the specified state.
+
+ .PARAMETER state
+ The state to set the controls to.
+ #>
+
+ param (
+ [boolean]$state
+ )
+
+ $sync["WPFScanUpdates"].IsEnabled = $state
+ $sync["WPFUpdateScanHistory"].IsEnabled = $state
+ $sync["WPFUpdateSelectedInstall"].IsEnabled = $state
+ $sync["WPFUpdateAllInstall"].IsEnabled = $state
+}
+
+
+function Invoke-WPFUpdateScan {
+ <#
+ .SYNOPSIS
+ Scans for Windows updates and history and builds the DataGrids for the UI.
+
+ .PARAMETER type
+ The type of scan to perform.
+
+ #>
+
+ param (
+ [string]$type
+ )
+
+ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo"
+ Invoke-WinUtilUpdateControls -state $false
+
+ Invoke-WPFRunspace -ArgumentList $type -DebugPreference $DebugPreference -ScriptBlock {
+ param ($type)
+ try {
+ Invoke-WinUtilInitializeModule -module "PSWindowsUpdate"
+ switch ($type) {
+ "updates" {
+ $sync.form.Dispatcher.Invoke([action] { $sync["WPFUpdatesList"].ItemsSource = $null })
+ Write-Host "Scanning for Windows updates..."
+ $updates = Get-WindowsUpdate -ErrorAction SilentlyContinue
+ Write-Host "Found $($updates.Count) updates."
+
+ # Build the list of items first
+ $items = foreach ($update in $updates) {
+ [PSCustomObject]@{
+ LongTitle = $update.Title
+ ComputerName = $update.ComputerName
+ KB = $update.KB
+ Size = $update.Size
+ Title = $update.Title -replace '\s*\(KB\d+\)', '' -replace '\s*KB\d+\b', ''
+ Status = "Not Installed"
+ }
+ }
+
+ $Computers = $updates.ComputerName | Select-Object -Unique
+
+ # Update the DataGrid at once
+ $sync.form.Dispatcher.Invoke([action] {
+ $sync["WPFUpdatesList"].ItemsSource = $items
+ $sync["WPFUpdatesList"].Columns[0].Visibility = if ($Computers.Count -gt 1) { "Visible" } else { "Collapsed" }
+ })
+ }
+ "history" {
+ $sync.form.Dispatcher.Invoke([action] { $sync["WPFUpdateHistory"].ItemsSource = $null })
+ Write-Host "Scanning for Windows update history..."
+ $history = Get-WUHistory -Last 50 -ErrorAction Stop
+ if (!$history) {
+ Write-Host "No update history available."
+ return
+ }
+
+ # Build the list of history items first
+ $items = foreach ($update in $history) {
+ [PSCustomObject]@{
+ ComputerName = $update.ComputerName
+ Result = $update.Result
+ Title = $update.Title -replace '\s*\(KB\d+\)', '' -replace '\s*KB\d+\b', ''
+ KB = $update.KB
+ Date = $update.Date
+ }
+ }
+
+ $Computers = $history.ComputerName | Select-Object -Unique
+
+ # Update the DataGrid at once
+ $sync.form.Dispatcher.Invoke([action] {
+ $sync["WPFUpdateHistory"].ItemsSource = $items
+ $sync["WPFUpdateHistory"].Columns[0].Visibility = if ($Computers.Count -gt 1) { "Visible" } else { "Collapsed" }
+ })
+ Write-Host "Scanning for Windows update history completed"
+ }
+ }
+
+ $sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
+ }
+ catch {
+ $sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "Error" -overlay "warning" })
+ Write-Host "Error during scan: $_" -ForegroundColor Red
+ } finally {
+ $sync.form.Dispatcher.Invoke([action] { Invoke-WinUtilUpdateControls -state $true })
+ }
+ }
+}
diff --git a/functions/public/Invoke-WinUtilInitializeModule.ps1 b/functions/public/Invoke-WinUtilInitializeModule.ps1
new file mode 100644
index 00000000..4089faba
--- /dev/null
+++ b/functions/public/Invoke-WinUtilInitializeModule.ps1
@@ -0,0 +1,28 @@
+function Invoke-WinUtilInitializeModule {
+ <#
+ .SYNOPSIS
+ Initializes and imports a specified PowerShell module.
+
+ .PARAMETER module
+ The name of the module to be installed and imported. If the module is not already available, it will be installed for the current user.
+
+ #>
+
+ param (
+ [string]$module
+ )
+
+ Invoke-WPFRunspace -ArgumentList $module -DebugPreference $DebugPreference -ScriptBlock {
+ param ($module)
+ try {
+ if (-not (Get-Module -ListAvailable -Name $module)) {
+ Write-Host "Installing $module module..."
+ Install-Module -Name $module -Force -Scope CurrentUser
+ }
+ Import-Module $module -ErrorAction Stop
+ Write-Host "Imported $module module successfully"
+ } catch {
+ Write-Host "Error importing $module module: $_" -ForegroundColor Red
+ }
+ }
+}
diff --git a/xaml/inputXML.xaml b/xaml/inputXML.xaml
index 5de6af1f..05d7d6fb 100644
--- a/xaml/inputXML.xaml
+++ b/xaml/inputXML.xaml
@@ -842,6 +842,182 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1132,100 +1308,232 @@
-
+
-
-
+
+
-
-
-
+
-
-
-
+
+
+
+
-
- Default Windows Update Configuration
-
- - No modifications to Windows defaults
-
- - Removes any custom update settings
-
- Note: This resets your Windows Update settings to default out of the box settings. It removes ANY policy or customization that has been done to Windows Update.
-
-
-
+ Content="Default"
+ Width="Auto"
+ Margin="0,2"
+ ToolTip="Default Windows Update Configuration
- No modifications to Windows defaults
- Removes any custom update settings
Note: This resets your Windows Update settings to default out of the box settings. It removes ANY policy or customization that has been done to Windows Update."/>
-
-
-
-
- Balanced Security Configuration
-
- - Feature updates delayed by 2 years
-
- - Security updates installed after 4 days
-
- Feature Updates: New features and potential bugs
-
- Security Updates: Critical security patches
-
- Note: This only applies to Pro systems that can use group policy.
-
-
-
+ Content="Security"
+ Width="Auto"
+ Margin="0,2"
+ ToolTip="Balanced Security Configuration
- Feature updates delayed by 2 years
- Security updates installed after 4 days
Feature Updates: New features and potential bugs
Security Updates: Critical security patches
Note: This only applies to Pro systems that can use group policy."/>
-
-
-
-
- !! Not Recommended !!
-
- - Disables ALL Windows Updates
-
- - Increases security risks
-
- - Only use for isolated systems
-
- Warning: Your system will be vulnerable without security updates.
-
+ Margin="0,2"
+ ToolTip="!! Not Recommended !!
- Disables ALL Windows Updates
- Increases security risks
- Only use for isolated systems
Warning: Your system will be vulnerable without security updates."/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+ Note: Updates may require a system restart to complete installation. Make sure to save any work before proceeding.
+
+
+
-
+