diff --git a/docs/assets/Install-Tab-Dark.png b/docs/assets/Install-Tab-Dark.png index fc07c072..234d3688 100644 Binary files a/docs/assets/Install-Tab-Dark.png and b/docs/assets/Install-Tab-Dark.png differ diff --git a/docs/dev/tweaks/Essential-Tweaks/Powershell7.md b/docs/dev/tweaks/Essential-Tweaks/Powershell7.md index 03474481..ab9ae36c 100644 --- a/docs/dev/tweaks/Essential-Tweaks/Powershell7.md +++ b/docs/dev/tweaks/Essential-Tweaks/Powershell7.md @@ -69,7 +69,7 @@ function Invoke-WPFTweakPS7{ Write-Host "Powershell 7 is already installed." } else { Write-Host "Installing Powershell 7..." - Invoke-WinUtilWingetProgram -Action Install -Programs @("Microsoft.PowerShell") + Install-WinUtilProgramWinget -Action Install -Programs @("Microsoft.PowerShell") } $targetTerminalName = "PowerShell" } @@ -105,10 +105,10 @@ function Invoke-WPFTweakPS7{ } ``` -## Function: Invoke-WinUtilWingetProgram +## Function: Install-WinUtilProgramWinget ```powershell -Function Invoke-WinUtilWingetProgram { +Function Install-WinUtilProgramWinget { <# .SYNOPSIS Runs the designated action on the provided programs using Winget diff --git a/docs/userguide.md b/docs/userguide.md index 7dac8c9a..2aa94df6 100644 --- a/docs/userguide.md +++ b/docs/userguide.md @@ -29,6 +29,11 @@ * Click the `Clear Selection` button. * This will unselect all checked programs. +=== "prefer Chocolatey" + * Check the `prefer Chocolatey` checkbox + * By default Winutil will use winget to install/upgrade/remove packages and fallback to Chocolatey. This option reverses the preference. + * This preference will be used for all Buttons on the Install page and persist across Winutil restarts + ![Install Image](assets/Install-Tab-Dark.png#only-dark) ![Install Image](assets/Install-Tab-Light.png#only-light) !!! tip diff --git a/functions/private/Install-WinUtilChoco.ps1 b/functions/private/Install-WinUtilChoco.ps1 index 37655b9c..254feba7 100644 --- a/functions/private/Install-WinUtilChoco.ps1 +++ b/functions/private/Install-WinUtilChoco.ps1 @@ -15,8 +15,8 @@ function Install-WinUtilChoco { } Write-Host "Seems Chocolatey is not installed, installing now." - Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) -ErrorAction Stop - powershell choco feature enable -n allowGlobalConfirmation + Start-Process -FilePath "powershell" -ArgumentList "Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) -ErrorAction Stop" -Wait -NoNewWindow + Start-Process -FilePath "powershell" -ArgumentList "choco feature enable -n allowGlobalConfirmation" -Wait -NoNewWindow } catch { Write-Host "===========================================" -Foregroundcolor Red diff --git a/functions/private/Install-WinUtilProgramChoco.ps1 b/functions/private/Install-WinUtilProgramChoco.ps1 index b66c88b9..b20f4b6f 100644 --- a/functions/private/Install-WinUtilProgramChoco.ps1 +++ b/functions/private/Install-WinUtilProgramChoco.ps1 @@ -1,102 +1,258 @@ function Install-WinUtilProgramChoco { <# .SYNOPSIS - Manages the provided programs using Chocolatey + Manages the installation or uninstallation of a list of Chocolatey packages. - .PARAMETER ProgramsToInstall - A list of programs to manage + .PARAMETER Programs + A string array containing the programs to be installed or uninstalled. - .PARAMETER manage - The action to perform on the programs, can be either 'Installing' or 'Uninstalling' + .PARAMETER Action + Specifies the action to perform: "Install" or "Uninstall". The default value is "Install". - .NOTES - The triple quotes are required any time you need a " in a normal script block. + .DESCRIPTION + This function processes a list of programs to be managed using Chocolatey. Depending on the specified action, it either installs or uninstalls each program in the list, updating the taskbar progress accordingly. After all operations are completed, temporary output files are cleaned up. + + .EXAMPLE + Install-WinUtilProgramChoco -Programs @("7zip","chrome") -Action "Uninstall" #> param( - [Parameter(Mandatory, Position=0)] - [PsCustomObject]$ProgramsToInstall, + [Parameter(Mandatory, Position = 0)] + [string[]]$Programs, - [Parameter(Position=1)] - [String]$manage = "Installing" + [Parameter(Position = 1)] + [String]$Action = "Install" ) - $x = 0 - $count = $ProgramsToInstall.Count - - # This check isn't really necessary, as there's a couple of checks before this Private Function gets called, but just to make sure ;) - if($count -le 0) { - throw "Private Function 'Install-WinUtilProgramChoco' expected Parameter 'ProgramsToInstall' to be of size 1 or greater, instead got $count,`nPlease double check your code and re-compile WinUtil." + function Initialize-OutputFile { + <# + .SYNOPSIS + Initializes an output file by removing any existing file and creating a new, empty file at the specified path. + + .PARAMETER filePath + The full path to the file to be initialized. + + .DESCRIPTION + This function ensures that the specified file is reset by removing any existing file at the provided path and then creating a new, empty file. It is useful when preparing a log or output file for subsequent operations. + + .EXAMPLE + Initialize-OutputFile -filePath "C:\temp\output.txt" + #> + + param ($filePath) + Remove-Item -Path $filePath -Force -ErrorAction SilentlyContinue + New-Item -ItemType File -Path $filePath | Out-Null } - - Write-Progress -Activity "$manage Applications" -Status "Starting" -PercentComplete 0 - Write-Host "===========================================" - Write-Host "-- Configuring Chocolatey pacakages ---" - Write-Host "===========================================" - Foreach ($Program in $ProgramsToInstall) { - Write-Progress -Activity "$manage Applications" -Status "$manage $($Program.choco) $($x + 1) of $count" -PercentComplete $($x/$count*100) - if($manage -eq "Installing") { - write-host "Starting install of $($Program.choco) with Chocolatey." - try { - $tryUpgrade = $false - $installOutputFilePath = "$env:TEMP\Install-WinUtilProgramChoco.install-command.output.txt" - New-Item -ItemType File -Path $installOutputFilePath - $chocoInstallStatus = $(Start-Process -FilePath "choco" -ArgumentList "install $($Program.choco) -y" -Wait -PassThru -RedirectStandardOutput $installOutputFilePath).ExitCode - if(($chocoInstallStatus -eq 0) -AND (Test-Path -Path $installOutputFilePath)) { - $keywordsFound = Get-Content -Path $installOutputFilePath | Where-Object {$_ -match "reinstall" -OR $_ -match "already installed"} - if ($keywordsFound) { - $tryUpgrade = $true + + function Run-ChocoCommand { + <# + .SYNOPSIS + Executes a Chocolatey command with the specified arguments and returns the exit code. + + .PARAMETER arguments + The arguments to be passed to the Chocolatey command. + + .DESCRIPTION + This function runs a specified Chocolatey command by passing the provided arguments to the `choco` executable. It waits for the process to complete and then returns the exit code, allowing the caller to determine success or failure based on the exit code. + + .RETURNS + [int] + The exit code of the Chocolatey command. + + .EXAMPLE + $exitCode = Run-ChocoCommand -arguments "install 7zip -y" + #> + + param ($arguments) + return (Start-Process -FilePath "choco" -ArgumentList $arguments -Wait -PassThru).ExitCode + } + + function Check-UpgradeNeeded { + <# + .SYNOPSIS + Checks if an upgrade is needed for a Chocolatey package based on the content of a log file. + + .PARAMETER filePath + The path to the log file that contains the output of a Chocolatey install command. + + .DESCRIPTION + This function reads the specified log file and checks for keywords that indicate whether an upgrade is needed. It returns a boolean value indicating whether the terms "reinstall" or "already installed" are present, which suggests that the package might need an upgrade. + + .RETURNS + [bool] + True if the log file indicates that an upgrade is needed; otherwise, false. + + .EXAMPLE + $isUpgradeNeeded = Check-UpgradeNeeded -filePath "C:\temp\install-output.txt" + #> + + param ($filePath) + return Get-Content -Path $filePath | Select-String -Pattern "reinstall|already installed" -Quiet + } + + function Update-TaskbarProgress { + <# + .SYNOPSIS + Updates the taskbar progress based on the current installation progress. + + .PARAMETER currentIndex + The current index of the program being installed or uninstalled. + + .PARAMETER totalPrograms + The total number of programs to be installed or uninstalled. + + .DESCRIPTION + This function calculates the progress of the installation or uninstallation process and updates the taskbar accordingly. The taskbar is set to "Normal" if all programs have been processed, otherwise, it is set to "Error" as a placeholder. + + .EXAMPLE + Update-TaskbarProgress -currentIndex 3 -totalPrograms 10 + #> + + param ( + [int]$currentIndex, + [int]$totalPrograms + ) + $progressState = if ($currentIndex -eq $totalPrograms) { "Normal" } else { "Error" } + $sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state $progressState -value ($currentIndex / $totalPrograms) }) + } + + function Install-ChocoPackage { + <# + .SYNOPSIS + Installs a Chocolatey package and optionally upgrades it if needed. + + .PARAMETER Program + A string containing the name of the Chocolatey package to be installed. + + .PARAMETER currentIndex + The current index of the program in the list of programs to be managed. + + .PARAMETER totalPrograms + The total number of programs to be installed. + + .DESCRIPTION + This function installs a Chocolatey package by running the `choco install` command. If the installation output indicates that an upgrade might be needed, the function will attempt to upgrade the package. The taskbar progress is updated after each package is processed. + + .EXAMPLE + Install-ChocoPackage -Program $Program -currentIndex 0 -totalPrograms 5 + #> + + param ( + [string]$Program, + [int]$currentIndex, + [int]$totalPrograms + ) + + $installOutputFile = "$env:TEMP\Install-WinUtilProgramChoco.install-command.output.txt" + Initialize-OutputFile $installOutputFile + + Write-Host "Starting installation of $Program with Chocolatey." + + try { + $installStatusCode = Run-ChocoCommand "install $Program -y --log-file $installOutputFile" + if ($installStatusCode -eq 0) { + + if (Check-UpgradeNeeded $installOutputFile) { + $upgradeStatusCode = Run-ChocoCommand "upgrade $Program -y" + Write-Host "$Program was" $(if ($upgradeStatusCode -eq 0) { "upgraded successfully." } else { "not upgraded." }) + } + else { + Write-Host "$Program installed successfully." } } - # TODO: Implement the Upgrade part using 'choco upgrade' command, this will make choco consistent with WinGet, as WinGet tries to Upgrade when you use the install command. - if ($tryUpgrade) { - throw "Automatic Upgrade for Choco isn't implemented yet, a feature to make it consistent with WinGet, the install command using choco simply failed because $($Program.choco) is already installed." - } - if(($chocoInstallStatus -eq 0) -AND ($tryUpgrade -eq $false)) { - Write-Host "$($Program.choco) installed successfully using Chocolatey." - $X++ - $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value ($x/$count) }) - continue - } else { - Write-Host "Failed to install $($Program.choco) using Chocolatey, Chocolatey output:`n`n$(Get-Content -Path $installOutputFilePath)." - $X++ - $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -value ($x/$count) }) - } - } catch { - Write-Host "Failed to install $($Program.choco) due to an error: $_" - $X++ - $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -value ($x/$count) }) + else { + Write-Host "Failed to install $Program." } } - - if($manage -eq "Uninstalling") { - write-host "Starting uninstall of $($Program.choco) with Chocolatey." + catch { + Write-Host "Failed to install $Program due to an error: $_" + } + finally { + Update-TaskbarProgress $currentIndex $totalPrograms + } + } + + function Uninstall-ChocoPackage { + <# + .SYNOPSIS + Uninstalls a Chocolatey package and any related metapackages. + + .PARAMETER Program + A string containing the name of the Chocolatey package to be uninstalled. + + .PARAMETER currentIndex + The current index of the program in the list of programs to be managed. + + .PARAMETER totalPrograms + The total number of programs to be uninstalled. + + .DESCRIPTION + This function uninstalls a Chocolatey package and any related metapackages (e.g., .install or .portable variants). It updates the taskbar progress after processing each package. + + .EXAMPLE + Uninstall-ChocoPackage -Program $Program -currentIndex 0 -totalPrograms 5 + #> + + param ( + [string]$Program, + [int]$currentIndex, + [int]$totalPrograms + ) + + $uninstallOutputFile = "$env:TEMP\Install-WinUtilProgramChoco.uninstall-command.output.txt" + Initialize-OutputFile $uninstallOutputFile + + Write-Host "Searching for metapackages of $Program (.install or .portable)" + $chocoPackages = ((choco list | Select-String -Pattern "$Program(\.install|\.portable)?").Matches.Value) -join " " + if ($chocoPackages) { + Write-Host "Starting uninstallation of $chocoPackages with Chocolatey." try { - $uninstallOutputFilePath = "$env:TEMP\Install-WinUtilProgramChoco.uninstall-command.output.txt" - New-Item -ItemType File -Path $uninstallOutputFilePath - $chocoUninstallStatus = $(Start-Process -FilePath "choco" -ArgumentList "uninstall $($Program.choco) -y" -Wait -PassThru).ExitCode - if($chocoUninstallStatus -eq 0) { - Write-Host "$($Program.choco) uninstalled successfully using Chocolatey." - $x++ - $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value ($x/$count) }) - continue - } else { - Write-Host "Failed to uninstall $($Program.choco) using Chocolatey, Chocolatey output:`n`n$(Get-Content -Path $uninstallOutputFilePath)." - $x++ - $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -value ($x/$count) }) - } - } catch { - Write-Host "Failed to uninstall $($Program.choco) due to an error: $_" - $x++ - $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -value ($x/$count) }) + $uninstallStatusCode = Run-ChocoCommand "uninstall $chocoPackages -y" + Write-Host "$Program" $(if ($uninstallStatusCode -eq 0) { "uninstalled successfully." } else { "failed to uninstall." }) } + catch { + Write-Host "Failed to uninstall $Program due to an error: $_" + } + finally { + Update-TaskbarProgress $currentIndex $totalPrograms + } + } + else { + Write-Host "$Program is not installed." + } } + + $totalPrograms = $Programs.Count + if ($totalPrograms -le 0) { + throw "Parameter 'Programs' must have at least one item." } - Write-Progress -Activity "$manage Applications" -Status "Finished" -Completed - # Cleanup leftovers files - if(Test-Path -Path $installOutputFilePath) { Remove-Item -Path $installOutputFilePath } - if(Test-Path -Path $uninstallOutputFilePath) { Remove-Item -Path $uninstallOutputFilePath } + Write-Host "===========================================" + Write-Host "-- Configuring Chocolatey packages ---" + Write-Host "===========================================" - return; + for ($currentIndex = 0; $currentIndex -lt $totalPrograms; $currentIndex++) { + $Program = $Programs[$currentIndex] + Set-WinUtilProgressBar -label "$Action $($Program)" -percent ($currentIndex / $totalPrograms * 100) + $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($currentIndex / $totalPrograms)}) + + switch ($Action) { + "Install" { + Install-ChocoPackage -Program $Program -currentIndex $currentIndex -totalPrograms $totalPrograms + } + "Uninstall" { + Uninstall-ChocoPackage -Program $Program -currentIndex $currentIndex -totalPrograms $totalPrograms + } + default { + throw "Invalid action parameter value: '$Action'." + } + } + } + Set-WinUtilProgressBar -label "$($Action)ation done" -percent 100 + # Cleanup Output Files + $outputFiles = @("$env:TEMP\Install-WinUtilProgramChoco.install-command.output.txt", "$env:TEMP\Install-WinUtilProgramChoco.uninstall-command.output.txt") + foreach ($filePath in $outputFiles) { + Remove-Item -Path $filePath -Force -ErrorAction SilentlyContinue + } } + diff --git a/functions/private/Invoke-WinUtilWingetProgram.ps1 b/functions/private/Install-WinUtilProgramWinget.ps1 similarity index 99% rename from functions/private/Invoke-WinUtilWingetProgram.ps1 rename to functions/private/Install-WinUtilProgramWinget.ps1 index f3d495f7..994d10b7 100644 --- a/functions/private/Invoke-WinUtilWingetProgram.ps1 +++ b/functions/private/Install-WinUtilProgramWinget.ps1 @@ -1,4 +1,4 @@ -Function Invoke-WinUtilWingetProgram { +Function Install-WinUtilProgramWinget { <# .SYNOPSIS Runs the designated action on the provided programs using Winget diff --git a/functions/private/Invoke-WinUtilCurrentSystem.ps1 b/functions/private/Invoke-WinUtilCurrentSystem.ps1 index 505942b5..e62568f4 100644 --- a/functions/private/Invoke-WinUtilCurrentSystem.ps1 +++ b/functions/private/Invoke-WinUtilCurrentSystem.ps1 @@ -13,6 +13,16 @@ Function Invoke-WinUtilCurrentSystem { param( $CheckBox ) + if ($CheckBox -eq "choco") { + $apps = (choco list | Select-String -Pattern "^\S+").Matches.Value + $filter = Get-WinUtilVariables -Type Checkbox | Where-Object {$psitem -like "WPFInstall*"} + $sync.GetEnumerator() | Where-Object {$psitem.Key -in $filter} | ForEach-Object { + $dependencies = @($sync.configs.applications.$($psitem.Key).choco -split ";") + if ($dependencies -in $apps) { + Write-Output $psitem.name + } + } + } if ($checkbox -eq "winget") { diff --git a/functions/public/Invoke-WPFGetInstalled.ps1 b/functions/public/Invoke-WPFGetInstalled.ps1 index 6f5a326a..c27fd13c 100644 --- a/functions/public/Invoke-WPFGetInstalled.ps1 +++ b/functions/public/Invoke-WPFGetInstalled.ps1 @@ -1,6 +1,6 @@ function Invoke-WPFGetInstalled { <# - + TODO: Add the Option to use Chocolatey as Engine .SYNOPSIS Invokes the function that gets the checkboxes to check in a new runspace @@ -16,12 +16,12 @@ function Invoke-WPFGetInstalled { return } - if(((Test-WinUtilPackageManager -winget) -eq "not-installed") -and $checkbox -eq "winget") { + if(($sync.WPFpreferChocolatey.IsChecked -eq $false) -and ((Test-WinUtilPackageManager -winget) -eq "not-installed") -and $checkbox -eq "winget") { return } - - Invoke-WPFRunspace -ArgumentList $checkbox -DebugPreference $DebugPreference -ScriptBlock { - param($checkbox, $DebugPreference) + $preferChoco = $sync.WPFpreferChocolatey.IsChecked + Invoke-WPFRunspace -ArgumentList $checkbox, $preferChoco -DebugPreference $DebugPreference -ScriptBlock { + param($checkbox, $preferChoco, $DebugPreference) $sync.ProcessRunning = $true $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" }) @@ -32,8 +32,12 @@ function Invoke-WPFGetInstalled { if($checkbox -eq "tweaks") { Write-Host "Getting Installed Tweaks..." } - - $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox $checkbox + if ($preferChoco -and $checkbox -eq "winget") { + $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox "choco" + } + else{ + $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox $checkbox + } $sync.form.Dispatcher.invoke({ foreach($checkbox in $Checkboxes) { diff --git a/functions/public/Invoke-WPFInstall.ps1 b/functions/public/Invoke-WPFInstall.ps1 index 0d880c93..f1605061 100644 --- a/functions/public/Invoke-WPFInstall.ps1 +++ b/functions/public/Invoke-WPFInstall.ps1 @@ -19,10 +19,9 @@ function Invoke-WPFInstall { [System.Windows.MessageBox]::Show($WarningMsg, $AppTitle, [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } - - - Invoke-WPFRunspace -ArgumentList $PackagesToInstall -DebugPreference $DebugPreference -ScriptBlock { - param($PackagesToInstall, $DebugPreference) + $ChocoPreference = $($sync.WPFpreferChocolatey.IsChecked) + Invoke-WPFRunspace -ArgumentList $PackagesToInstall,$ChocoPreference -DebugPreference $DebugPreference -ScriptBlock { + param($PackagesToInstall, $ChocoPreference, $DebugPreference) if ($PackagesToInstall.count -eq 1) { $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }) } else { @@ -30,17 +29,29 @@ function Invoke-WPFInstall { } $packagesWinget, $packagesChoco = { $packagesWinget = [System.Collections.ArrayList]::new() - $packagesChoco = [System.Collections.Generic.List`1[System.Object]]::new() - foreach ($package in $PackagesToInstall) { + $packagesChoco = [System.Collections.ArrayList]::new() + + foreach ($package in $PackagesToInstall) { + if ($ChocoPreference) { + if ($package.choco -eq "na") { + $packagesWinget.add($package.winget) + Write-Host "Queueing $($package.winget) for Winget install" + } else { + $null = $packagesChoco.add($package.choco) + Write-Host "Queueing $($package.choco) for Chocolatey install" + } + } + else { if ($package.winget -eq "na") { - $packagesChoco.add($package) + $packagesChoco.add($package.choco) Write-Host "Queueing $($package.choco) for Chocolatey install" } else { $null = $packagesWinget.add($($package.winget)) Write-Host "Queueing $($package.winget) for Winget install" } } - return $packagesWinget, $packagesChoco + } + return $packagesWinget, $packagesChoco }.Invoke($PackagesToInstall) try { @@ -48,12 +59,12 @@ function Invoke-WPFInstall { $errorPackages = @() if($packagesWinget.Count -gt 0) { Install-WinUtilWinget - $errorPackages += Invoke-WinUtilWingetProgram -Action Install -Programs $packagesWinget - $errorPackages| ForEach-Object {if($_.choco -ne "na") {$packagesChoco += $_}} + Install-WinUtilProgramWinget -Action Install -Programs $packagesWinget + } if($packagesChoco.Count -gt 0) { Install-WinUtilChoco - Install-WinUtilProgramChoco -ProgramsToInstall $packagesChoco + Install-WinUtilProgramChoco -Action Install -Programs $packagesChoco } Write-Host "===========================================" Write-Host "-- Installs have finished ---" diff --git a/functions/public/Invoke-WPFInstallUpgrade.ps1 b/functions/public/Invoke-WPFInstallUpgrade.ps1 index e30f5f1f..c86ee123 100644 --- a/functions/public/Invoke-WPFInstallUpgrade.ps1 +++ b/functions/public/Invoke-WPFInstallUpgrade.ps1 @@ -2,25 +2,35 @@ function Invoke-WPFInstallUpgrade { <# .SYNOPSIS - Invokes the function that upgrades all installed programs using winget + Invokes the function that upgrades all installed programs #> - if((Test-WinUtilPackageManager -winget) -eq "not-installed") { - return + if ($sync.WPFpreferChocolatey.IsChecked) { + Install-WinUtilChoco + $chocoUpgradeStatus = (Start-Process "choco" -ArgumentList "upgrade all -y" -Wait -PassThru -NoNewWindow).ExitCode + if ($chocoUpgradeStatus -eq 0) { + Write-Host "Upgrade Successful" + } + else{ + Write-Host "Error Occured. Return Code: $chocoUpgradeStatus" + } } + else{ + if((Test-WinUtilPackageManager -winget) -eq "not-installed") { + return + } - if(Get-WinUtilInstallerProcess -Process $global:WinGetInstall) { - $msg = "[Invoke-WPFInstallUpgrade] Install process is currently running. Please check for a powershell window labeled 'Winget Install'" - [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) - return + if(Get-WinUtilInstallerProcess -Process $global:WinGetInstall) { + $msg = "[Invoke-WPFInstallUpgrade] Install process is currently running. Please check for a powershell window labeled 'Winget Install'" + [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) + return + } + + Update-WinUtilProgramWinget + + Write-Host "===========================================" + Write-Host "-- Updates started ---" + Write-Host "-- You can close this window if desired ---" + Write-Host "===========================================" } - - # Set-WinUtilTaskbaritem -state "Indeterminate" - - Update-WinUtilProgramWinget - - Write-Host "===========================================" - Write-Host "-- Updates started ---" - Write-Host "-- You can close this window if desired ---" - Write-Host "===========================================" } diff --git a/functions/public/Invoke-WPFRunspace.ps1 b/functions/public/Invoke-WPFRunspace.ps1 index dfb3a6cd..440a13b7 100644 --- a/functions/public/Invoke-WPFRunspace.ps1 +++ b/functions/public/Invoke-WPFRunspace.ps1 @@ -30,7 +30,9 @@ function Invoke-WPFRunspace { # Add Scriptblock and Arguments to runspace $script:powershell.AddScript($ScriptBlock) - $script:powershell.AddArgument($ArgumentList) + foreach ($Argument in $ArgumentList) { + $script:powershell.AddArgument($Argument) + } $script:powershell.AddArgument($DebugPreference) # Pass DebugPreference to the script block $script:powershell.RunspacePool = $sync.runspace diff --git a/functions/public/Invoke-WPFTweakPS7.ps1 b/functions/public/Invoke-WPFTweakPS7.ps1 index 3e291c4c..6b1959c2 100644 --- a/functions/public/Invoke-WPFTweakPS7.ps1 +++ b/functions/public/Invoke-WPFTweakPS7.ps1 @@ -17,7 +17,7 @@ function Invoke-WPFTweakPS7{ Write-Host "Powershell 7 is already installed." } else { Write-Host "Installing Powershell 7..." - Invoke-WinUtilWingetProgram -Action Install -Programs @("Microsoft.PowerShell") + Install-WinUtilProgramWinget -Action Install -Programs @("Microsoft.PowerShell") } $targetTerminalName = "PowerShell" } diff --git a/functions/public/Invoke-WPFUnInstall.ps1 b/functions/public/Invoke-WPFUnInstall.ps1 index 19aec2d2..a1a670a3 100644 --- a/functions/public/Invoke-WPFUnInstall.ps1 +++ b/functions/public/Invoke-WPFUnInstall.ps1 @@ -28,38 +28,51 @@ function Invoke-WPFUnInstall { $confirm = [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) if($confirm -eq "No") {return} + $ChocoPreference = $($sync.WPFpreferChocolatey.IsChecked) - - Invoke-WPFRunspace -ArgumentList $PackagesToInstall -DebugPreference $DebugPreference -ScriptBlock { - param($PackagesToInstall, $DebugPreference) + Invoke-WPFRunspace -ArgumentList $PackagesToInstall, $ChocoPreference -DebugPreference $DebugPreference -ScriptBlock { + param($PackagesToInstall, $ChocoPreference, $DebugPreference) if ($PackagesToInstall.count -eq 1) { $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }) } else { $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }) } $packagesWinget, $packagesChoco = { - $packagesWinget = [System.Collections.Generic.List`1[System.Object]]::new() - $packagesChoco = [System.Collections.Generic.List`1[System.Object]]::new() - foreach ($package in $PackagesToInstall) { - if ($package.winget -eq "na") { - $packagesChoco.add($package) - Write-Host "Queueing $($package.choco) for Chocolatey Uninstall" + $packagesWinget = [System.Collections.ArrayList]::new() + $packagesChoco = [System.Collections.ArrayList]::new() + + foreach ($package in $PackagesToInstall) { + if ($ChocoPreference) { + if ($package.choco -eq "na") { + $packagesWinget.add($package.winget) + Write-Host "Queueing $($package.winget) for Winget uninstall" } else { - $packagesWinget.add($($package.winget)) - Write-Host "Queueing $($package.winget) for Winget Uninstall" + $null = $packagesChoco.add($package.choco) + Write-Host "Queueing $($package.choco) for Chocolatey uninstall" } } - return $packagesWinget, $packagesChoco + else { + if ($package.winget -eq "na") { + $packagesChoco.add($package.choco) + Write-Host "Queueing $($package.choco) for Chocolatey uninstall" + } else { + $null = $packagesWinget.add($($package.winget)) + Write-Host "Queueing $($package.winget) for Winget uninstall" + } + } + } + return $packagesWinget, $packagesChoco }.Invoke($PackagesToInstall) + try { $sync.ProcessRunning = $true # Install all selected programs in new window if($packagesWinget.Count -gt 0) { - Invoke-WinUtilWingetProgram -Action Uninstall -Programs $packagesWinget + Install-WinUtilProgramWinget -Action Uninstall -Programs $packagesWinget } if($packagesChoco.Count -gt 0) { - Install-WinUtilProgramChoco -ProgramsToInstall $packagesChoco -Manage "Uninstalling" + Install-WinUtilProgramChoco -Action Uninstall -Programs $packagesChoco } Write-Host "===========================================" diff --git a/scripts/main.ps1 b/scripts/main.ps1 index ef206840..e96dc944 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -116,6 +116,14 @@ Invoke-WPFUIElements -configVariable $sync.configs.feature -targetGridName "feat $xaml.SelectNodes("//*[@Name]") | ForEach-Object {$sync["$("$($psitem.Name)")"] = $sync["Form"].FindName($psitem.Name)} +#Persist the Chocolatey preference across winutil restarts +$ChocoPreferencePath = "$env:LOCALAPPDATA\winutil\preferChocolatey.ini" +$sync.WPFpreferChocolatey.Add_Checked({New-Item -Path $ChocoPreferencePath -Force }) +$sync.WPFpreferChocolatey.Add_Unchecked({Remove-Item $ChocoPreferencePath -Force}) +if (Test-Path $ChocoPreferencePath) { + $sync.WPFpreferChocolatey.IsChecked = $true +} + $sync.keys | ForEach-Object { if($sync.$psitem) { if($($sync["$psitem"].GetType() | Select-Object -ExpandProperty Name) -eq "ToggleButton") { diff --git a/xaml/inputXML.xaml b/xaml/inputXML.xaml index 1dd80b94..fbf8d35d 100644 --- a/xaml/inputXML.xaml +++ b/xaml/inputXML.xaml @@ -833,6 +833,9 @@