Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/src/content/docs/code-reference/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ Invoke-WinUtilISOCleanAndReset (optional)
**Modification Safety**:
- Windows PE and specialize set hardware bypass and setup safeguards; `WinUtil-PostInstall.ps1` applies additional registry changes at first logon
- Original ISO never modified; only working copy
- Logged to the WinUtil session log and the live UI status panel
- Logged to the shared `%LocalAppData%\winutil\logs\winutil_<timestamp>.log` session file and the live UI status panel, so the log survives cleanup
- DISM handles image dismount with automatic cleanup and discard on error

### Win11 Creator Registry Tweaks
Expand Down
20 changes: 6 additions & 14 deletions functions/private/Find-AppsByNameOrDescription.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -91,43 +91,35 @@ function Find-AppsByNameOrDescription {
return
}

# Escape wildcard characters for literal matching
$escapedSearchString = [System.Management.Automation.WildcardPattern]::Escape($SearchString)

# IndexOf with OrdinalIgnoreCase is faster than -like with wildcard escaping
$sync.ItemsControl.Items | ForEach-Object {
# Each item is a StackPanel container with Children[0] = label, Children[1] = WrapPanel
if ($_.Children.Count -ge 2) {
$categoryLabel = $_.Children[0]
$wrapPanel = $_.Children[1]
$categoryHasMatch = $false

$categoryLabel.Visibility = [Windows.Visibility]::Visible

foreach ($appControl in $wrapPanel.Children) {
$appTag = $appControl.Tag
$appEntry = $null

if (-not [string]::IsNullOrWhiteSpace($appTag) -and $sync.configs.applicationsHashtable.ContainsKey($appTag)) {
$appEntry = $sync.configs.applicationsHashtable[$appTag]
}

if ($null -ne $appEntry) {
$categoryMatch = -not $hasCategories -or $activeCategories -contains $appEntry.Category
$textMatch = -not $hasSearch -or
$appEntry.Content -like "*$escapedSearchString*" -or
$appEntry.Description -like "*$escapedSearchString*" -or
$appTag -like "*$escapedSearchString*"
([string]$appEntry.Content).IndexOf($SearchString, [System.StringComparison]::OrdinalIgnoreCase) -ge 0 -or
([string]$appEntry.Description).IndexOf($SearchString, [System.StringComparison]::OrdinalIgnoreCase) -ge 0 -or
([string]$appTag).IndexOf($SearchString, [System.StringComparison]::OrdinalIgnoreCase) -ge 0

if ($categoryMatch -and $textMatch) {
$appControl.Visibility = [Windows.Visibility]::Visible
$categoryHasMatch = $true
}
else {
} else {
$appControl.Visibility = [Windows.Visibility]::Collapsed
}
}
else {
# Hide app if no entry found (data integrity issue)
} else {
$appControl.Visibility = [Windows.Visibility]::Collapsed
}
}
Expand Down
382 changes: 93 additions & 289 deletions functions/private/Find-TweaksByNameOrDescription.ps1

Large diffs are not rendered by default.

62 changes: 25 additions & 37 deletions functions/private/Invoke-WinUtilCurrentSystem.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ Function Invoke-WinUtilCurrentSystem {
)
if ($CheckBox -eq "choco") {
$apps = (choco list | Select-String -Pattern "^\S+").Matches.Value
$sync.configs.applicationsHashtable.GetEnumerator() | ForEach-Object {
$packageId = ($_.Value.choco -split ";")[-1].Trim()
foreach ($app in $sync.configs.applicationsHashtable.GetEnumerator()) {
$packageId = ($app.Value.choco -split ";")[-1].Trim()
if ($packageId -ne "na" -and $packageId -in $apps) {
Write-Output $_.Key
Write-Output $app.Key
}
}

Expand Down Expand Up @@ -59,18 +59,18 @@ Function Invoke-WinUtilCurrentSystem {
$idColumnStart = $Matches[1].Length
}

$sync.configs.applicationsHashtable.GetEnumerator() | ForEach-Object {
$packageId = (($_.Value.winget -split ";")[-1] -replace "^msstore:", "").Trim()
foreach ($app in $sync.configs.applicationsHashtable.GetEnumerator()) {
$packageId = (($app.Value.winget -split ";")[-1] -replace "^msstore:", "").Trim()
if ([string]::IsNullOrWhiteSpace($packageId) -or $packageId -eq "na") {
return
continue
}

$escapedPackageId = [regex]::Escape($packageId)
$packagePattern = "(?im)[^\S\r\n]{2,}$escapedPackageId(?=[^\S\r\n]{2,}|$)"
# Skip rows whose Name has combining marks or emoji: they are more characters than columns and shift the offset
$idColumnPattern = "(?im)(?<=^[^\r\n\p{M}\p{Cs}\p{Cf}]{$($idColumnStart - 1)}[^\S\r\n])$escapedPackageId(?=[^\S\r\n]|$)"
if ($installedProgramText -match $packagePattern -or ($idColumnStart -and $installedProgramText -match $idColumnPattern)) {
Write-Output $_.Key
Write-Output $app.Key
}
}
}
Expand All @@ -80,29 +80,28 @@ Function Invoke-WinUtilCurrentSystem {
if (!(Test-Path 'HKU:\')) {$null = (New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS)}
$readErrorAction = if ($StopOnReadError) { "Stop" } else { "SilentlyContinue" }

$sync.configs.tweaks | Get-Member -MemberType NoteProperty | ForEach-Object {

$Config = $psitem.Name
$entry = $sync.configs.tweaks.$Config
foreach ($prop in $sync.configs.tweaks.PSObject.Properties) {
$Config = $prop.Name
$entry = $prop.Value
$registryKeys = $entry.registry
$serviceKeys = $entry.service
$entryType = $entry.Type

if (($registryKeys -or $serviceKeys) -and $entryType -ne "Combobox") {
$Values = @()
$allMatch = $true

if ($entryType -eq "Toggle") {
if (-not (Get-WinUtilToggleStatus $Config `
-BypassCache:$BypassToggleStatusCache `
-StopOnReadError:$StopOnReadError)) {
$values += $False
$allMatch = $false
}
} else {
$registryMatchCount = 0
$registryTotal = 0

Foreach ($tweaks in $registryKeys) {
Foreach ($tweak in $tweaks) {
foreach ($tweaks in $registryKeys) {
foreach ($tweak in $tweaks) {
$registryTotal++
$regstate = $null

Expand All @@ -116,15 +115,9 @@ Function Invoke-WinUtilCurrentSystem {

if ($null -eq $regstate) {
switch ($tweak.DefaultState) {
"true" {
$regstate = $tweak.Value
}
"false" {
$regstate = $tweak.OriginalValue
}
default {
$regstate = $tweak.OriginalValue
}
"true" { $regstate = $tweak.Value }
"false" { $regstate = $tweak.OriginalValue }
default { $regstate = $tweak.OriginalValue }
}
}

Expand All @@ -135,37 +128,32 @@ Function Invoke-WinUtilCurrentSystem {
}

if ($registryTotal -gt 0 -and $registryMatchCount -ne $registryTotal) {
$values += $False
$allMatch = $false
}
}

Foreach ($tweaks in $serviceKeys) {
Foreach ($tweak in $tweaks) {
foreach ($tweaks in $serviceKeys) {
foreach ($tweak in $tweaks) {
try {
$Service = Get-Service -Name $tweak.Name -ErrorAction $readErrorAction
} catch {
if ($StopOnReadError -and $_.FullyQualifiedErrorId -like "NoServiceFoundForGivenName*") {
# A removed optional service means this tweak is not applied; it does
# not make the registry and service state for every other tweak unknown.
$values += $False
$allMatch = $false
continue
}
throw
}

if ($Service) {
$actualValue = $Service.StartType
$expectedValue = $tweak.StartupType
if ($expectedValue -ne $actualValue) {
$values += $False
}
} elseif ($StopOnReadError) {
$values += $False
if (($Service -and $tweak.StartupType -ne $Service.StartType) -or
(-not $Service -and $StopOnReadError)) {
$allMatch = $false
}
}
}

if ($values -notcontains $false) {
if ($allMatch) {
Write-Output $Config
}
}
Expand Down
27 changes: 13 additions & 14 deletions functions/private/Invoke-WinUtilTweaks.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,17 @@ function Invoke-WinUtilTweaks {
}
}
if ($sync.configs.tweaks.$CheckBox.service) {
$sync.configs.tweaks.$CheckBox.service | ForEach-Object {
foreach ($item in $sync.configs.tweaks.$CheckBox.service) {
$changeservice = $true

# KeepServiceStartup protects a service the user (or another tool) changed away from
# the value this tweak expects. Undo uses the same rule in reverse: only restore
# OriginalType when the service still sits at the StartupType this tweak applies.
# This compares current state, not history: a service already at StartupType
# before apply is indistinguishable from one changed by this tweak.
$expectedType = if ($undo) { $psitem.StartupType } else { $psitem.$($values.OriginalService) }
$expectedType = if ($undo) { $item.StartupType } else { $item.$($values.OriginalService) }
if ($KeepServiceStartup) {
$serviceName = $psitem.Name
$serviceName = $item.Name
try {
# Check if the service exists
$service = Get-Service -Name $serviceName -ErrorAction Stop
Expand All @@ -76,29 +76,28 @@ function Invoke-WinUtilTweaks {
}

if ($changeservice) {
Set-WinUtilService -Name $psitem.Name -StartupType $psitem.$($values.Service)
Set-WinUtilService -Name $item.Name -StartupType $item.$($values.Service)
}
}
}
if ($sync.configs.tweaks.$CheckBox.registry) {
$sync.configs.tweaks.$CheckBox.registry | Where-Object { -not $psitem.Values } | ForEach-Object {
Set-WinUtilRegistry -Name $psitem.Name -Path $psitem.Path -Type $psitem.Type -Value $psitem.$($values.registry)
foreach ($reg in $sync.configs.tweaks.$CheckBox.registry) {
if ($reg.Values) { continue }
Set-WinUtilRegistry -Name $reg.Name -Path $reg.Path -Type $reg.Type -Value $reg.$($values.registry)
}
}
if ($sync.configs.tweaks.$CheckBox.$($values.ScriptType)) {
$sync.configs.tweaks.$CheckBox.$($values.ScriptType) | ForEach-Object {
$Scriptblock = [scriptblock]::Create($psitem)
foreach ($scr in $sync.configs.tweaks.$CheckBox.$($values.ScriptType)) {
$Scriptblock = [scriptblock]::Create($scr)
Invoke-WinUtilScript -ScriptBlock $scriptblock -Name $CheckBox
}
}

if (!$undo) {
if($sync.configs.tweaks.$CheckBox.appx) {
$sync.configs.tweaks.$CheckBox.appx | ForEach-Object {
Remove-WinUtilAPPX -Name $psitem
}
Remove-WinUtilProvisionedAPPX -PackageList $sync.configs.tweaks.$CheckBox.appx
if (!$undo -and $sync.configs.tweaks.$CheckBox.appx) {
foreach ($pkg in $sync.configs.tweaks.$CheckBox.appx) {
Remove-WinUtilAPPX -Name $pkg
}
Remove-WinUtilProvisionedAPPX -PackageList $sync.configs.tweaks.$CheckBox.appx
}
$errorCount = [int]$global:WinUtilJobErrorCount - $errorsBefore
if ($errorCount -gt 0) {
Expand Down
37 changes: 8 additions & 29 deletions functions/private/Show-CustomDialog.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -130,57 +130,36 @@ function Show-CustomDialog {

$dialog.Content = $border

# Create a grid for layout inside the Border
$grid = New-Object Windows.Controls.Grid
$border.Child = $grid

# Uncomment the following line to show gridlines
#$grid.ShowGridLines = $true

# Add the following line to set the background color of the grid
$grid.Background = [Windows.Media.Brushes]::Transparent
# Add the following line to make the Grid stretch
$grid.HorizontalAlignment = [Windows.HorizontalAlignment]::Stretch
$grid.VerticalAlignment = [Windows.VerticalAlignment]::Stretch

# Add the following line to make the Border stretch
$border.HorizontalAlignment = [Windows.HorizontalAlignment]::Stretch
$border.VerticalAlignment = [Windows.VerticalAlignment]::Stretch

# Set up Row Definitions
$row0 = New-Object Windows.Controls.RowDefinition
$row0.Height = [Windows.GridLength]::Auto

$row1 = New-Object Windows.Controls.RowDefinition
$row1.Height = [Windows.GridLength]::new(1, [Windows.GridUnitType]::Star)

$row2 = New-Object Windows.Controls.RowDefinition
$row2.Height = [Windows.GridLength]::Auto

# Add Row Definitions to Grid
$row0 = New-Object Windows.Controls.RowDefinition; $row0.Height = [Windows.GridLength]::Auto
$row1 = New-Object Windows.Controls.RowDefinition; $row1.Height = [Windows.GridLength]::new(1, [Windows.GridUnitType]::Star)
$row2 = New-Object Windows.Controls.RowDefinition; $row2.Height = [Windows.GridLength]::Auto
$grid.RowDefinitions.Add($row0)
$grid.RowDefinitions.Add($row1)
$grid.RowDefinitions.Add($row2)

# Add StackPanel for horizontal layout with margins
$stackPanel = New-Object Windows.Controls.StackPanel
$stackPanel.Margin = New-Object Windows.Thickness(10) # Add margins around the stack panel
$stackPanel.Margin = New-Object Windows.Thickness(10)
$stackPanel.Orientation = [Windows.Controls.Orientation]::Horizontal
$stackPanel.HorizontalAlignment = [Windows.HorizontalAlignment]::Left # Align to the left
$stackPanel.VerticalAlignment = [Windows.VerticalAlignment]::Top # Align to the top

$stackPanel.HorizontalAlignment = [Windows.HorizontalAlignment]::Left
$stackPanel.VerticalAlignment = [Windows.VerticalAlignment]::Top
$grid.Children.Add($stackPanel)
[Windows.Controls.Grid]::SetRow($stackPanel, 0) # Set the row to the second row (0-based index)
[Windows.Controls.Grid]::SetRow($stackPanel, 0)

# Add SVG path to the stack panel
$stackPanel.Children.Add((Invoke-WinUtilAssets -Type "logo" -Size $LogoSize))

# Add "Winutil" text
$winutilTextBlock = New-Object Windows.Controls.TextBlock
$winutilTextBlock.Text = "WinUtil"
$winutilTextBlock.FontSize = $HeaderFontSize
$winutilTextBlock.Foreground = $LogoColor
$winutilTextBlock.Margin = New-Object Windows.Thickness(10, 10, 10, 5) # Add margins around the text block
$winutilTextBlock.Margin = New-Object Windows.Thickness(10, 10, 10, 5)
$stackPanel.Children.Add($winutilTextBlock)
# Add TextBlock for information with text wrapping and margins
$messageTextBlock = New-Object Windows.Controls.TextBlock
Expand Down
35 changes: 13 additions & 22 deletions functions/private/Test-WinUtilPackageManager.ps1
Original file line number Diff line number Diff line change
@@ -1,37 +1,28 @@
function Test-WinUtilPackageManager {
<#

.SYNOPSIS
Checks if WinGet and/or Choco are installed

Checks if WinGet and/or Choco are installed.
.PARAMETER winget
Check if WinGet is installed

Check if WinGet is installed.
.PARAMETER choco
Check if Chocolatey is installed

Check if Chocolatey is installed.
#>

Param(
[System.Management.Automation.SwitchParameter]$winget,
[System.Management.Automation.SwitchParameter]$choco
)

if ($winget) {
if (Get-Command winget -ErrorAction SilentlyContinue) {
$status = "installed"
} else {
$status = "not-installed"
}
}
# Handle missing switch - callers rely on the return value
if (-not $winget -and -not $choco) { return "not-installed" }

if ($choco) {
if (Get-Command choco -ErrorAction SilentlyContinue) {
$status = "installed"
} else {
$status = "not-installed"
$cmds = @()
if ($winget) { $cmds += "winget" }
if ($choco) { $cmds += "choco" }

foreach ($cmd in $cmds) {
if (-not (Get-Command $cmd -ErrorAction SilentlyContinue)) {
return "not-installed"
}
}

return $status
return "installed"
}
Loading
Loading