mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2026-10-24 05:50:58 +00:00
* Detect WinGet-fallback apps in Chocolatey-mode Get Installed In Chocolatey mode, apps with an empty or "na" Chocolatey ID are installed through WinGet (Get-WinUtilSelectedPackages), but Get Installed only checked choco list, so they were never selected. After the Chocolatey match, collect those fallback apps with the same rule as install routing. When there are any and WinGet is installed, reuse the WinGet matcher with one winget list and keep only the fallback apps. A WinGet failure warns and keeps the Chocolatey results. WinGet mode and install routing are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Skip winget when no fallback app has a WinGet ID Only treat an app as a WinGet fallback when it also has a usable WinGet ID, matching Get-WinUtilSelectedPackages, so Chocolatey mode does not run winget list when no app could be found that way. Reword the Show Installed Apps note so it no longer says detection always uses WinGet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
165 lines
6.8 KiB
PowerShell
165 lines
6.8 KiB
PowerShell
Function Invoke-WinUtilCurrentSystem {
|
|
|
|
<#
|
|
|
|
.SYNOPSIS
|
|
Checks to see what tweaks have already been applied and what programs are installed, and checks the according boxes
|
|
|
|
.EXAMPLE
|
|
InvokeWinUtilCurrentSystem -Checkbox "winget"
|
|
|
|
#>
|
|
|
|
param(
|
|
$CheckBox,
|
|
[switch]$BypassToggleStatusCache,
|
|
[switch]$StopOnReadError
|
|
)
|
|
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()
|
|
if ($packageId -ne "na" -and $packageId -in $apps) {
|
|
Write-Output $_.Key
|
|
}
|
|
}
|
|
|
|
# Apps without a Chocolatey package are installed through WinGet (see Get-WinUtilSelectedPackages),
|
|
# so check those against one winget list
|
|
$wingetFallbackKeys = @($sync.configs.applicationsHashtable.GetEnumerator() | Where-Object {
|
|
([string]::IsNullOrWhiteSpace([string]$_.Value.choco) -or $_.Value.choco -eq "na") -and
|
|
-not ([string]::IsNullOrWhiteSpace([string]$_.Value.winget) -or $_.Value.winget -eq "na")
|
|
} | ForEach-Object { $_.Key })
|
|
if ($wingetFallbackKeys.Count -gt 0 -and (Test-WinUtilPackageManager -winget) -eq "installed") {
|
|
try {
|
|
Invoke-WinUtilCurrentSystem -CheckBox "winget" | Where-Object { $_ -in $wingetFallbackKeys }
|
|
} catch {
|
|
Write-Warning "Could not check apps installed through WinGet: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($checkbox -eq "winget") {
|
|
$originalEncoding = [Console]::OutputEncoding
|
|
try {
|
|
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
|
|
$installedProgramOutput = @(winget list --accept-source-agreements --disable-interactivity 2>&1)
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "winget list failed with exit code $LASTEXITCODE."
|
|
}
|
|
} finally {
|
|
[Console]::OutputEncoding = $originalEncoding
|
|
}
|
|
$installedProgramText = $installedProgramOutput -join "`n"
|
|
|
|
$sync.configs.applicationsHashtable.GetEnumerator() | ForEach-Object {
|
|
$packageId = (($_.Value.winget -split ";")[-1] -replace "^msstore:", "").Trim()
|
|
if ([string]::IsNullOrWhiteSpace($packageId) -or $packageId -eq "na") {
|
|
return
|
|
}
|
|
|
|
$packagePattern = "(?im)[^\S\r\n]{2,}$([regex]::Escape($packageId))(?=[^\S\r\n]{2,}|$)"
|
|
if ($installedProgramText -match $packagePattern) {
|
|
Write-Output $_.Key
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($CheckBox -eq "tweaks") {
|
|
|
|
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
|
|
$registryKeys = $entry.registry
|
|
$serviceKeys = $entry.service
|
|
$entryType = $entry.Type
|
|
|
|
if (($registryKeys -or $serviceKeys) -and $entryType -ne "Combobox") {
|
|
$Values = @()
|
|
|
|
if ($entryType -eq "Toggle") {
|
|
if (-not (Get-WinUtilToggleStatus $Config `
|
|
-BypassCache:$BypassToggleStatusCache `
|
|
-StopOnReadError:$StopOnReadError)) {
|
|
$values += $False
|
|
}
|
|
} else {
|
|
$registryMatchCount = 0
|
|
$registryTotal = 0
|
|
|
|
Foreach ($tweaks in $registryKeys) {
|
|
Foreach ($tweak in $tweaks) {
|
|
$registryTotal++
|
|
$regstate = $null
|
|
|
|
if (Test-Path $tweak.Path -ErrorAction $readErrorAction) {
|
|
if ($StopOnReadError) {
|
|
$regstate = (Get-ItemProperty -Path $tweak.Path -ErrorAction Stop).$($tweak.Name)
|
|
} else {
|
|
$regstate = Get-ItemProperty -Name $tweak.Name -Path $tweak.Path -ErrorAction SilentlyContinue | Select-Object -ExpandProperty $($tweak.Name)
|
|
}
|
|
}
|
|
|
|
if ($null -eq $regstate) {
|
|
switch ($tweak.DefaultState) {
|
|
"true" {
|
|
$regstate = $tweak.Value
|
|
}
|
|
"false" {
|
|
$regstate = $tweak.OriginalValue
|
|
}
|
|
default {
|
|
$regstate = $tweak.OriginalValue
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($regstate -eq $tweak.Value) {
|
|
$registryMatchCount++
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($registryTotal -gt 0 -and $registryMatchCount -ne $registryTotal) {
|
|
$values += $False
|
|
}
|
|
}
|
|
|
|
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
|
|
continue
|
|
}
|
|
throw
|
|
}
|
|
|
|
if ($Service) {
|
|
$actualValue = $Service.StartType
|
|
$expectedValue = $tweak.StartupType
|
|
if ($expectedValue -ne $actualValue) {
|
|
$values += $False
|
|
}
|
|
} elseif ($StopOnReadError) {
|
|
$values += $False
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($values -notcontains $false) {
|
|
Write-Output $Config
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|