Compare commits

..

2 Commits

Author SHA1 Message Date
e4b2a38372 fix a few tweak errors 2025-03-03 14:31:18 -06:00
94c5d89430 fix winget for good (#3096) 2025-03-03 14:16:53 -06:00
10 changed files with 189 additions and 724 deletions

View File

@ -1,5 +1,6 @@
# Import the function (adjust the path according to your setup)
. "./functions/private/Get-WinUtilWingetLatest.ps1"
. "./functions/private/Install-WinUtilWinget.ps1"
. "./functions/private/Test-WinUtilPackageManager.ps1"
# Set up Information stream to be visible
$InformationPreference = "Continue"
@ -7,20 +8,7 @@ $InformationPreference = "Continue"
Write-Host "Starting Winget installation test..." -ForegroundColor Cyan
try {
# Test the function with verbose output
Write-Host "Attempting to run Get-WinUtilWingetLatest..." -ForegroundColor Cyan
Get-WinUtilWingetLatest -Verbose
# Verify Winget is working
if (Get-Command winget -ErrorAction SilentlyContinue) {
Write-Host "Success! Winget is installed and accessible." -ForegroundColor Green
# Display Winget version
Write-Host "`nWinget version:" -ForegroundColor Cyan
winget --version
} else {
Write-Host "Warning: Winget is installed but not accessible in the current session. You may need to restart your terminal." -ForegroundColor Yellow
}
Install-WinUtilWinget
} catch {
Write-Host "Error occurred during testing: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "Stack Trace:" -ForegroundColor Red

View File

@ -423,26 +423,6 @@
"StartupType": "Automatic",
"OriginalType": "Automatic"
},
{
"Name": "DoSvc",
"StartupType": "AutomaticDelayedStart",
"OriginalType": "Automatic"
},
{
"Name": "DsSvc",
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "DsmSvc",
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "DusmSvc",
"StartupType": "Automatic",
"OriginalType": "Automatic"
},
{
"Name": "EFS",
"StartupType": "Manual",
@ -898,11 +878,6 @@
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "SgrmBroker",
"StartupType": "Automatic",
"OriginalType": "Automatic"
},
{
"Name": "SharedAccess",
"StartupType": "Manual",
@ -933,11 +908,6 @@
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "StateRepository",
"StartupType": "Manual",
"OriginalType": "Automatic"
},
{
"Name": "StiSvc",
"StartupType": "Manual",
@ -973,11 +943,6 @@
"StartupType": "Automatic",
"OriginalType": "Automatic"
},
{
"Name": "TextInputManagementService",
"StartupType": "Manual",
"OriginalType": "Automatic"
},
{
"Name": "Themes",
"StartupType": "Automatic",

View File

@ -1,104 +0,0 @@
function Get-WinUtilWingetLatest {
[CmdletBinding()]
param()
<#
.SYNOPSIS
Uses GitHub API to check for the latest release of Winget.
.DESCRIPTION
This function first attempts to update WinGet using winget itself, then falls back to manual installation if needed.
#>
$ProgressPreference = "SilentlyContinue"
$InformationPreference = 'Continue'
try {
$wingetCmd = Get-Command winget -ErrorAction Stop
Write-Information "Attempting to update WinGet using WinGet..."
$result = Start-Process -FilePath "`"$($wingetCmd.Source)`"" -ArgumentList "install -e --accept-source-agreements --accept-package-agreements Microsoft.AppInstaller" -Wait -NoNewWindow -PassThru
if ($result.ExitCode -ne 0) {
throw "WinGet update failed with exit code: $($result.ExitCode)"
}
return $true
}
catch {
Write-Information "WinGet not found or update failed. Attempting to install from Microsoft Store..."
try {
# Try to close any running WinGet processes
Get-Process -Name "DesktopAppInstaller", "winget" -ErrorAction SilentlyContinue | ForEach-Object {
Write-Information "Stopping running WinGet process..."
$_.Kill()
Start-Sleep -Seconds 2
}
# Try to load Windows Runtime assemblies more reliably
$null = [System.Runtime.WindowsRuntime.WindowsRuntimeSystemExtensions]
Add-Type -AssemblyName System.Runtime.WindowsRuntime
# Load required assemblies from Windows SDK
$null = @(
[Windows.Management.Deployment.PackageManager, Windows.Management.Deployment, ContentType = WindowsRuntime]
[Windows.Foundation.Uri, Windows.Foundation, ContentType = WindowsRuntime]
[Windows.Management.Deployment.DeploymentOptions, Windows.Management.Deployment, ContentType = WindowsRuntime]
)
# Initialize PackageManager
$packageManager = New-Object Windows.Management.Deployment.PackageManager
# Rest of the Microsoft Store installation logic
$appxPackage = "https://aka.ms/getwinget"
$uri = New-Object Windows.Foundation.Uri($appxPackage)
$deploymentOperation = $packageManager.AddPackageAsync($uri, $null, "Add")
# Add timeout check for deployment operation
$timeout = 300
$timer = [System.Diagnostics.Stopwatch]::StartNew()
while ($deploymentOperation.Status -eq 0) {
if ($timer.Elapsed.TotalSeconds -gt $timeout) {
throw "Installation timed out after $timeout seconds"
}
Start-Sleep -Milliseconds 100
}
if ($deploymentOperation.Status -eq 1) {
Write-Information "Successfully installed WinGet from Microsoft Store"
return $true
} else {
throw "Installation failed with status: $($deploymentOperation.Status)"
}
}
catch [System.Management.Automation.RuntimeException] {
Write-Information "Windows Runtime components not available. Attempting manual download..."
try {
# Try to close any running WinGet processes
Get-Process -Name "DesktopAppInstaller", "winget" -ErrorAction SilentlyContinue | ForEach-Object {
Write-Information "Stopping running WinGet process..."
$_.Kill()
Start-Sleep -Seconds 2
}
# Fallback to direct download from GitHub
$apiUrl = "https://api.github.com/repos/microsoft/winget-cli/releases/latest"
$release = Invoke-RestMethod -Uri $apiUrl
$msixBundleUrl = ($release.assets | Where-Object { $_.name -like "*.msixbundle" }).browser_download_url
$tempFile = Join-Path $env:TEMP "Microsoft.DesktopAppInstaller.msixbundle"
Invoke-WebRequest -Uri $msixBundleUrl -OutFile $tempFile
Add-AppxPackage -Path $tempFile -ErrorAction Stop
Remove-Item $tempFile -Force
Write-Information "Successfully installed WinGet from GitHub release"
return $true
}
catch {
Write-Error "Failed to install WinGet: $_"
return $false
}
}
catch {
Write-Error "Failed to install WinGet: $_"
return $false
}
}
}

View File

@ -33,18 +33,118 @@ function Install-WinUtilWinget {
return
}
# Install Winget via GitHub method.
# Used part of my own script with some modification: ruxunderscore/windows-initialization
Write-Host "Downloading Winget and License File`r"
Get-WinUtilWingetLatest
Write-Host "Enabling NuGet and Module..."
Install-PackageProvider -Name NuGet -Force
Install-Module -Name Microsoft.WinGet.Client -Force
# Winget only needs a refresh of the environment variables to be used.
Write-Host "Attempting to install/update Winget`r"
try {
$wingetCmd = Get-Command winget -ErrorAction Stop
Write-Information "Attempting to update WinGet using WinGet..."
$result = Start-Process -FilePath "`"$($wingetCmd.Source)`"" -ArgumentList "install -e --accept-source-agreements --accept-package-agreements Microsoft.AppInstaller" -Wait -NoNewWindow -PassThru
if ($result.ExitCode -ne 0) {
throw "WinGet update failed with exit code: $($result.ExitCode)"
}
Write-Output "Refreshing Environment Variables...`n"
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
return
} catch {
Write-Information "WinGet not found or update failed. Attempting to install from Microsoft Store..."
}
try {
# Try to close any running WinGet processes
Get-Process -Name "DesktopAppInstaller", "winget" -ErrorAction SilentlyContinue | ForEach-Object {
Write-Information "Stopping running WinGet process..."
$_.Kill()
Start-Sleep -Seconds 2
}
# Try to load Windows Runtime assemblies more reliably
$null = [System.Runtime.WindowsRuntime.WindowsRuntimeSystemExtensions]
Add-Type -AssemblyName System.Runtime.WindowsRuntime
# Load required assemblies from Windows SDK
$null = @(
[Windows.Management.Deployment.PackageManager, Windows.Management.Deployment, ContentType = WindowsRuntime]
[Windows.Foundation.Uri, Windows.Foundation, ContentType = WindowsRuntime]
[Windows.Management.Deployment.DeploymentOptions, Windows.Management.Deployment, ContentType = WindowsRuntime]
)
# Initialize PackageManager
$packageManager = New-Object Windows.Management.Deployment.PackageManager
# Rest of the Microsoft Store installation logic
$appxPackage = "https://aka.ms/getwinget"
$uri = New-Object Windows.Foundation.Uri($appxPackage)
$deploymentOperation = $packageManager.AddPackageAsync($uri, $null, "Add")
# Add timeout check for deployment operation
$timeout = 300
$timer = [System.Diagnostics.Stopwatch]::StartNew()
while ($deploymentOperation.Status -eq 0) {
if ($timer.Elapsed.TotalSeconds -gt $timeout) {
throw "Installation timed out after $timeout seconds"
}
Start-Sleep -Milliseconds 100
}
if ($deploymentOperation.Status -eq 1) {
Write-Information "Successfully installed WinGet from Microsoft Store"
Write-Output "Refreshing Environment Variables...`n"
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
return
} else {
throw "Installation failed with status: $($deploymentOperation.Status)"
}
} catch {
Write-Information "Microsoft Store installation failed. Attempting to install from Nuget..."
}
try {
## Nuget Method
Write-Host "Enabling NuGet and Module..."
# Enable TLS 1.2 for the PowerShell session
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Try to register the NuGet package source if not present
if (-not (Get-PackageSource -Name "NuGet" -ErrorAction SilentlyContinue)) {
Register-PackageSource -Name "NuGet" -Location "https://www.nuget.org/api/v2" -ProviderName NuGet -Force
}
# Install NuGet provider with error handling
try {
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Confirm:$false -ErrorAction Stop
} catch {
Write-Warning "Failed to install NuGet provider through standard method. Trying alternative approach..."
Install-PackageProvider -Name NuGet -Source "https://www.powershellgallery.com/api/v2" -Force -Confirm:$false
}
Install-Module -Name Microsoft.WinGet.Client -Confirm:$false -Force
# Check if WinGet was installed successfully through NuGet
$wingetCmd = Get-Command winget -ErrorAction Stop
Write-Information "Successfully installed WinGet through NuGet"
Write-Output "Refreshing Environment Variables...`n"
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
return
} catch {
Write-Warning "NuGet installation failed. Attempting to install from GitHub..."
}
# GitHub fallback installation method
$releases_url = "https://api.github.com/repos/microsoft/winget-cli/releases/latest"
$asset = (Invoke-RestMethod -Uri $releases_url).assets |
Where-Object { $_.name -match "\.msixbundle$" } |
Select-Object -First 1
$download_url = $asset.browser_download_url
$output_path = Join-Path $env:TEMP $asset.name
Invoke-WebRequest -Uri $download_url -OutFile $output_path
Add-AppxPackage -Path $output_path -ErrorAction Stop
# Verify installation
$wingetCmd = Get-Command winget -ErrorAction Stop
Write-Information "Successfully installed WinGet through GitHub"
Write-Output "Refreshing Environment Variables...`n"
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
return
} catch {
Write-Error "Failed to install Winget: $($_.Exception.Message)"
Write-Error "All installation methods failed. Unable to install WinGet."
throw
}
}

View File

@ -61,10 +61,5 @@ function Invoke-WPFButton {
"WPFWinUtilInstallPSProfile" {Invoke-WinUtilInstallPSProfile}
"WPFWinUtilUninstallPSProfile" {Invoke-WinUtilUninstallPSProfile}
"WPFWinUtilSSHServer" {Invoke-WPFSSHServer}
"WPFScanUpdates" {Invoke-WPFUpdatesScan}
"WPFShowUpdateHistory" { Invoke-WPFUpdateHistoryToggle }
"WPFUpdateSelectedInstall" {Invoke-WPFUpdateMGMT -Selected}
"WPFUpdateAllInstall" {Invoke-WPFUpdateMGMT -All}
"WPFUpdateScanHistory" {Invoke-WPFUpdateScanHistory}
}
}

View File

@ -1,11 +0,0 @@
function Invoke-WPFUpdateHistoryToggle {
if ($sync["WPFShowUpdateHistory"].Content -eq "Show History") {
$sync["WPFShowUpdateHistory"].Content = "Show available Updates"
$sync["HistoryGrid"].Visibility = "Visible"
$sync["UpdatesGrid"].Visibility = "Collapsed"
} else {
$sync["WPFShowUpdateHistory"].Content = "Show History"
$sync["HistoryGrid"].Visibility = "Collapsed"
$sync["UpdatesGrid"].Visibility = "Visible"
}
}

View File

@ -1,50 +0,0 @@
function Invoke-WPFUpdateMGMT {
param (
[switch]$Selected,
[switch]$All
)
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
if ($All) {
Write-Host "Installing all available updates ..."
Invoke-WPFRunspace -ArgumentList $sync["WPFUpdateVerbose"].IsChecked -DebugPreference $DebugPreference -ScriptBlock {
param ($WPFUpdateVerbose)
if ($WPFUpdateVerbose) {
Install-WindowsUpdate -Verbose -Confirm:$false -IgnoreReboot:$true -IgnoreRebootRequired:$true
} else {
Install-WindowsUpdate -Confirm:$false -IgnoreReboot:$true -IgnoreRebootRequired:$true
}
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
Write-Host "All Update Processes Completed"
#catch $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -overlay "warning" })
}
} elseif (($Selected) -and ($sync["WPFUpdatesList"].SelectedItems.Count -gt 0)) {
write-host "Installing selected updates..."
$selectedUpdates = $sync["WPFUpdatesList"].SelectedItems | ForEach-Object {
[PSCustomObject]@{
ComputerName = $_.ComputerName
Title = $_.LongTitle
KB = $_.KB
Size = $_.Size
}
}
Invoke-WPFRunspace -ParameterList @(("selectedUpdates", $selectedUpdates), ("WPFUpdateVerbose", $sync["WPFUpdateVerbose"].IsChecked)) -DebugPreference $DebugPreference -ScriptBlock {
param ($selectedUpdates, $WPFUpdateVerbose)
foreach ($update in $selectedUpdates) {
Write-Host "Installing update $($update.Title) on $($update.ComputerName)"
if ($WPFUpdateVerbose) {
Get-WindowsUpdate -ComputerName $update.ComputerName -Title $update.Title -Install -Confirm:$false -Verbose -IgnoreReboot:$true -IgnoreRebootRequired:$true
} else {
Get-WindowsUpdate -ComputerName $update.ComputerName -Title $update.Title -Install -Confirm:$false -IgnoreReboot:$true -IgnoreRebootRequired:$true
}
}
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
Write-Host "Selected Update Processes Completed"
#catch $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -overlay "warning" })
}
} else {
Write-Host "No updates selected"
return
}
}

View File

@ -1,49 +0,0 @@
function Invoke-WPFUpdateScanHistory {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
$sync["WPFUpdateHistory"].Items.Clear()
Invoke-WPFRunspace -DebugPreference $DebugPreference -ScriptBlock {
write-host "Scanning for Windows update history..."
$UpdateHistory = Get-WUHistory -Last 50 -ErrorAction SilentlyContinue
if ($UpdateHistory) {
foreach ($update in $UpdateHistory) {
$item = New-Object PSObject -Property @{
ComputerName = $update.ComputerName
Result = $update.Result
Title = $update.Title -replace '\s*\(KB\d+\)', '' -replace '\s*KB\d+\b', '' # Remove KB number from title, first in parentheses, then standalone
KB = $update.KB
Date = $update.Date
}
$Computers = $item | Select-Object -ExpandProperty ComputerName -Unique
$sync.form.Dispatcher.Invoke([action] {
$sync["WPFUpdateHistory"].Items.Add($item)
if ($item.Result -eq "Succeeded") {
# does not work : $sync["WPFUpdateHistory"].Items[$sync["WPFUpdateHistory"].Items.Count - 1].Foreground = "Green"
#write-host "$($item.Title) was successful"
}
elseif ($item.Result -eq "Failed") {
# does not work : $sync["WPFUpdateHistory"].Items[$sync["WPFUpdateHistory"].Items.Count - 1].Foreground = "Red"
#write-host "$($item.Title) failed"
}
})
}
write-host "Found $($UpdateHistory.Count) updates."
$sync.form.Dispatcher.Invoke([action] {
if ($Computers.Count -gt 1) {
$sync["WPFUpdateHistory"].Columns[0].Visibility = "Visible"
}
else {
Write-Debug "Hiding ComputerName column, only $item.ComputerName"
$sync["WPFUpdateHistory"].Columns[0].Visibility = "Collapsed"
}
})
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
#catch $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -overlay "warning" })
}
else {
$sync.form.Dispatcher.Invoke([action] {
$sync["WPFUpdateHistory"].Items.Clear()
})
Write-Host "No update history available."
}
}
}

View File

@ -1,61 +0,0 @@
function Invoke-WPFUpdatesScan {
Invoke-WPFRunspace -DebugPreference $DebugPreference -ScriptBlock {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
# Check if the PSWindowsUpdate module is installed
if (-not (Get-Module -ListAvailable -Name PSWindowsUpdate)) {
try {
Write-Host "PSWindowsUpdate module not found. Attempting to install..."
Install-Module -Name PSWindowsUpdate -Force -Scope CurrentUser
Write-Host "PSWindowsUpdate module installed successfully."
}
catch {
Write-Error "Failed to install PSWindowsUpdate module: $_"
return
}
}
# Import the module
try {
Import-Module PSWindowsUpdate -ErrorAction Stop
Write-Host "PSWindowsUpdate module imported successfully."
}
catch {
Write-Error "Failed to import PSWindowsUpdate module: $_"
return
}
try {
$sync.form.Dispatcher.Invoke([action] { $sync["WPFUpdatesList"].Items.Clear() })
Write-Host "Scanning for Windows updates..."
$updates = Get-WindowsUpdate -ErrorAction Stop
Write-Host "Found $($updates.Count) updates."
$sync.form.Dispatcher.Invoke([action] {
foreach ($update in $updates) {
$item = New-Object PSObject -Property @{
LongTitle = $update.Title
ComputerName = $update.ComputerName
KB = $update.KB
Size = $update.Size
Title = $update.Title -replace '\s*\(KB\d+\)', '' -replace '\s*KB\d+\b', '' # Remove KB number from title, first in parentheses, then standalone
Status = "Not Installed"
}
$Computers = $item | Select-Object -ExpandProperty ComputerName -Unique
$sync["WPFUpdatesList"].Items.Add($item)
}
if ($Computers.Count -gt 1) {
$sync["WPFUpdatesList"].Columns[0].Visibility = "Visible"
} else {
Write-Debug "Hiding ComputerName column, only $item.ComputerName"
$sync["WPFUpdatesList"].Columns[0].Visibility = "Collapsed"
}
})
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
} catch {
Write-Error "Error scanning for updates: $_"
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -overlay "warning" })
}
}
}

View File

@ -842,182 +842,6 @@
</MultiDataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="DataGrid">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource MainForegroundColor}" />
<Setter Property="BorderBrush" Value="{DynamicResource BorderColor}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FontSize" Value="{DynamicResource FontSize}" />
<Setter Property="FontFamily" Value="{DynamicResource FontFamily}" />
<Setter Property="RowBackground" Value="Transparent" />
<Setter Property="AlternatingRowBackground" Value="{DynamicResource AlternatingRowBackgroundColor}" />
<Setter Property="GridLinesVisibility" Value="None" />
<Setter Property="HeadersVisibility" Value="Column" />
<Setter Property="HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="VerticalScrollBarVisibility" Value="Auto" />
<Setter Property="SelectionMode" Value="Extended" />
<Setter Property="SelectionUnit" Value="FullRow" />
<Setter Property="CanUserAddRows" Value="False" />
<Setter Property="CanUserDeleteRows" Value="False" />
<Setter Property="CanUserReorderColumns" Value="False" />
<Setter Property="CanUserResizeRows" Value="True" />
<Setter Property="CanUserSortColumns" Value="True" />
<Setter Property="AutoGenerateColumns" Value="False" />
<Setter Property="Margin" Value="0,10,0,10" />
<Setter Property="CellStyle">
<Setter.Value>
<Style TargetType="DataGridCell">
<Setter Property="Padding" Value="10,6" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="4"
Margin="2,1"
Padding="{TemplateBinding Padding}">
<ContentPresenter VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundMouseoverColor}" />
<Setter Property="Foreground" Value="{DynamicResource MainForegroundColor}" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundSelectedColor}" />
<Setter Property="Foreground" Value="{DynamicResource MainForegroundColor}" />
<Setter Property="BorderThickness" Value="0" />
</Trigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
<Setter Property="RowStyle">
<Setter.Value>
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource MainForegroundColor}" />
<Setter Property="MinHeight" Value="35" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Margin" Value="0,1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridRow">
<Border x:Name="RowBorder"
BorderThickness="0"
BorderBrush="{DynamicResource BorderColor}"
Background="{TemplateBinding Background}"
CornerRadius="6"
Margin="4,2"
SnapsToDevicePixels="True">
<SelectiveScrollingGrid>
<SelectiveScrollingGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</SelectiveScrollingGrid.ColumnDefinitions>
<SelectiveScrollingGrid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</SelectiveScrollingGrid.RowDefinitions>
<DataGridCellsPresenter Grid.Column="1"
ItemsPanel="{TemplateBinding ItemsPanel}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<DataGridDetailsPresenter Grid.Column="1" Grid.Row="1"
Visibility="{TemplateBinding DetailsVisibility}"
SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen,
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
Converter={x:Static DataGrid.RowDetailsScrollingConverter},
ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}}"/>
<DataGridRowHeader Grid.RowSpan="2"
SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
Visibility="{Binding HeadersVisibility,
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
Converter={x:Static DataGrid.HeadersVisibilityConverter},
ConverterParameter={x:Static DataGridHeadersVisibility.Row}}"/>
</SelectiveScrollingGrid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundMouseoverColor}" />
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" BlurRadius="5" Opacity="0.2" Color="#000000" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundSelectedColor}" />
<Setter Property="Foreground" Value="{DynamicResource MainForegroundColor}" />
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="1" BlurRadius="7" Opacity="0.3" Color="#000000" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
<Setter Property="ColumnHeaderStyle">
<Setter.Value>
<Style TargetType="DataGridColumnHeader">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundColor}" />
<Setter Property="FontSize" Value="{DynamicResource FontSize}" />
<Setter Property="FontFamily" Value="{DynamicResource FontFamily}" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Padding" Value="10,8" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Margin" Value="2,0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridColumnHeader">
<Grid>
<Border Background="{TemplateBinding Background}"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="0,0,0,1"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="True" />
</Border>
<Path x:Name="SortArrow" Visibility="Collapsed"
HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,5,0" Fill="{DynamicResource ButtonForegroundColor}"
Width="8" Height="6" Stretch="Fill" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="SortDirection" Value="Ascending">
<Setter TargetName="SortArrow" Property="Visibility" Value="Visible"/>
<Setter TargetName="SortArrow" Property="Data" Value="M 0,5 L 8,5 L 4,0 Z"/>
</Trigger>
<Trigger Property="SortDirection" Value="Descending">
<Setter TargetName="SortArrow" Property="Visibility" Value="Visible"/>
<Setter TargetName="SortArrow" Property="Data" Value="M 0,0 L 8,0 L 4,5 Z"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{DynamicResource LinkHoverForegroundColor}" />
</Trigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Background="{DynamicResource MainBackgroundColor}" ShowGridLines="False" Name="WPFMainGrid" Width="Auto" Height="Auto" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
@ -1308,232 +1132,100 @@
</ScrollViewer>
</TabItem>
<TabItem Header="Updates" Visibility="Collapsed" Name="WPFTab4">
<!-- <ScrollViewer VerticalScrollBarVisibility="Auto" Margin="{DynamicResource TabContentMargin}"> -->
<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="{DynamicResource TabContentMargin}">
<Grid Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <!-- Row for the 3 columns -->
<RowDefinition Height="Auto"/> <!-- Row for Windows Version -->
</Grid.RowDefinitions>
<!-- Three columns container -->
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Left Column - Update Options -->
<Border Grid.Column="0" Style="{StaticResource BorderStyle}" VerticalAlignment="Stretch">
<StackPanel Margin="5">
<TextBlock Text="Update Presets" Margin="0,0,0,5"/>
<!-- Default Settings -->
<Border Grid.Column="0" Style="{StaticResource BorderStyle}">
<StackPanel>
<Button Name="WPFFixesUpdate"
Content="Default"
Width="Auto"
Margin="0,2"
ToolTip="Default Windows Update Configuration&#x0a;- No modifications to Windows defaults&#x0a;- Removes any custom update settings&#x0a;&#x0a;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."/>
<Button Name="WPFUpdatessecurity"
Content="Security"
Width="Auto"
Margin="0,2"
ToolTip="Balanced Security Configuration&#x0a;- Feature updates delayed by 2 years&#x0a;- Security updates installed after 4 days&#x0a;&#x0a;Feature Updates: New features and potential bugs&#x0a;Security Updates: Critical security patches&#x0a;&#x0a;Note: This only applies to Pro systems that can use group policy."/>
<Button Name="WPFUpdatesdisable"
Content="Disable"
Width="Auto"
Foreground="Red"
Margin="0,2"
ToolTip="!! Not Recommended !!&#x0a;- Disables ALL Windows Updates&#x0a;- Increases security risks&#x0a;- Only use for isolated systems&#x0a;&#x0a;Warning: Your system will be vulnerable without security updates."/>
FontSize="{DynamicResource ConfigTabButtonFontSize}"
Content="Default Settings"
Margin="10,5"
Padding="10"/>
<TextBlock Margin="10"
TextWrapping="Wrap"
Foreground="{DynamicResource MainForegroundColor}">
<Run FontWeight="Bold">Default Windows Update Configuration</Run>
<LineBreak/>
- No modifications to Windows defaults
<LineBreak/>
- Removes any custom update settings
<LineBreak/><LineBreak/>
<Run FontStyle="Italic" FontSize="11">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.</Run>
</TextBlock>
</StackPanel>
</Border>
<!-- Right Column - Updates List -->
<Border Grid.Column="1" Style="{StaticResource BorderStyle}" VerticalAlignment="Stretch">
<Grid Margin="5,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Security Settings -->
<Border Grid.Column="1" Style="{StaticResource BorderStyle}">
<StackPanel>
<Button Name="WPFUpdatessecurity"
FontSize="{DynamicResource ConfigTabButtonFontSize}"
Content="Security Settings"
Margin="10,5"
Padding="10"/>
<TextBlock Margin="10"
TextWrapping="Wrap"
Foreground="{DynamicResource MainForegroundColor}">
<Run FontWeight="Bold">Balanced Security Configuration</Run>
<LineBreak/>
- Feature updates delayed by 2 years
<LineBreak/>
- Security updates installed after 4 days
<LineBreak/><LineBreak/>
<Run FontWeight="SemiBold">Feature Updates:</Run> New features and potential bugs
<LineBreak/>
<Run FontWeight="SemiBold">Security Updates:</Run> Critical security patches
<LineBreak/><LineBreak/>
<Run FontStyle="Italic" FontSize="11">Note: This only applies to Pro systems that can use group policy.</Run>
</TextBlock>
</StackPanel>
</Border>
<!-- Toggle button at the top -->
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right" Margin="5">
<ToggleButton Name="WPFShowUpdateHistory"
Content="Show History"
Style="{StaticResource ToggleButtonStyle}"
Margin="5"
Padding="10,5"
ToolTip="Toggle between pending updates and update history"/>
</StackPanel>
<!-- Updates Grid - Visible by default -->
<Grid Grid.Row="1" Name="UpdatesGrid" Visibility="Visible">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button Name="WPFScanUpdates"
Content="Scan for Updates"
Grid.Row="0"
Margin="5"
HorizontalAlignment="Left"
Padding="10,5"/>
<DataGrid Name="WPFUpdatesList"
Grid.Row="1"
Margin="5"
AutoGenerateColumns="False"
Background="Transparent"
IsReadOnly="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<DataGrid.Columns>
<DataGridTextColumn Header="LongTitle"
Binding="{Binding LongTitle}"
Width="Auto"
Visibility="Collapsed"/>
<DataGridTextColumn Header="ComputerName"
Binding="{Binding ComputerName}"
Width="Auto"
Visibility="Collapsed"/>
<DataGridTextColumn Header="Title"
Binding="{Binding Title}"
Width="*"
MinWidth="100"/>
<DataGridTextColumn Header="KB"
Binding="{Binding KB}"
Width="Auto"
MinWidth="100">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Size"
Binding="{Binding Size}"
Width="Auto"
MinWidth="80">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Status"
Binding="{Binding Status}"
Width="Auto"
MinWidth="100">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<StackPanel Grid.Row="2"
Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="5">
<StackPanel VerticalAlignment="Center">
<CheckBox x:Name="WPFUpdateVerbose"
Content="Verbose Output"
Margin="5"
Padding="10,5"
ToolTip="Verbose output for update installation"
IsChecked="True"/>
</StackPanel>
<Button Name="WPFUpdateSelectedInstall"
Content="Install Selected"
Margin="5"
Padding="10,5"/>
<Button Name="WPFUpdateAllInstall"
Content="Install All"
Margin="5"
Padding="10,5"/>
</StackPanel>
</Grid>
<!-- History Grid - Collapsed by default -->
<Grid Grid.Row="1" Name="HistoryGrid" Visibility="Collapsed">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Name="WPFUpdateScanHistory"
Content="Scan History"
Grid.Row="0"
Margin="5"
HorizontalAlignment="Left"
Padding="10,5"/>
<DataGrid Name="WPFUpdateHistory"
Grid.Row="1"
Margin="5"
AutoGenerateColumns="False"
Background="Transparent"
IsReadOnly="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<DataGrid.Columns>
<DataGridTextColumn Header="ComputerName"
Binding="{Binding ComputerName}"
Width="Auto"
Visibility="Collapsed"/>
<DataGridTextColumn Header="Result"
Binding="{Binding Result}"
Width="Auto"
MinWidth="100">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Title"
Binding="{Binding Title}"
Width="*"/>
<DataGridTextColumn Header="KB"
Binding="{Binding KB}"
Width="Auto"
MinWidth="100">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn Header="Date"
Binding="{Binding Date}"
Width="Auto"
MinWidth="160">
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Grid>
<!-- Disable Updates -->
<Border Grid.Column="2" Style="{StaticResource BorderStyle}">
<StackPanel>
<Button Name="WPFUpdatesdisable"
FontSize="{DynamicResource ConfigTabButtonFontSize}"
Content="Disable All Updates"
Foreground="Red"
Margin="10,5"
Padding="10"/>
<TextBlock Margin="10"
TextWrapping="Wrap"
Foreground="{DynamicResource MainForegroundColor}">
<Run FontWeight="Bold" Foreground="Red">!! Not Recommended !!</Run>
<LineBreak/>
- Disables ALL Windows Updates
<LineBreak/>
- Increases security risks
<LineBreak/>
- Only use for isolated systems
<LineBreak/><LineBreak/>
<Run FontStyle="Italic" FontSize="11">Warning: Your system will be vulnerable without security updates.</Run>
</TextBlock>
</StackPanel>
</Border>
</Grid>
<Border Grid.Row="1" Style="{StaticResource BorderStyle}">
<StackPanel Background="{DynamicResource MainBackgroundColor}" Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Padding="10">
Note: Updates may require a system restart to complete installation. Make sure to save any work before proceeding.
</TextBlock>
</StackPanel>
</Border>
<!-- Future Implementation: Add Windows Version to updates panel -->
<Grid Name="updatespanel" Grid.Row="1" Background="Transparent">
</Grid>
</Grid>
<!-- </ScrollViewer> -->
</ScrollViewer>
</TabItem>
<TabItem Header="MicroWin" Visibility="Collapsed" Name="WPFTab5">
<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="{DynamicResource TabContentMargin}">