diff --git a/winutil.ps1 b/winutil.ps1 index 2ee3289f..2cee90f7 100644 --- a/winutil.ps1 +++ b/winutil.ps1 @@ -427,17 +427,16 @@ Function Get-WinUtilCheckBoxes { $group = if ($CheckBox.Key.StartsWith("WPFInstall")) { "Install" } elseif ($CheckBox.Key.StartsWith("WPFTweaks")) { "WPFTweaks" } elseif ($CheckBox.Key.StartsWith("WPFFeature")) { "WPFFeature" } - if ($group) { if ($CheckBox.Value.IsChecked -eq $true) { $feature = switch ($group) { "Install" { - $wingetValue = $sync.configs.applications.$($CheckBox.Name).winget - if (-not [string]::IsNullOrWhiteSpace($wingetValue) -and $wingetValue -ne "na") { - $wingetValue -split ";" - } else { - $sync.configs.applications.$($CheckBox.Name).choco + # Get the winget value + [PsCustomObject]@{ + winget="$($sync.configs.applications.$($CheckBox.Name).winget)"; + choco="$($sync.configs.applications.$($CheckBox.Name).choco)"; } + } default { $CheckBox.Name @@ -461,8 +460,7 @@ Function Get-WinUtilCheckBoxes { } } } - - return $Output + return $Output } function Get-WinUtilInstallerProcess { <# @@ -723,95 +721,144 @@ function Install-WinUtilChoco { } } -Function Install-WinUtilProgramWinget { - +function Install-WinUtilProgramChoco { <# .SYNOPSIS - Manages the provided programs using Winget - + Manages the provided programs using Chocolatey + .PARAMETER ProgramsToInstall - A list of programs to manage - + A list of programs to manage + .PARAMETER manage - The action to perform on the programs, can be either 'Installing' or 'Uninstalling' - + The action to perform on the programs, can be either 'Installing' or 'Uninstalling' + .NOTES - The triple quotes are required any time you need a " in a normal script block. + The triple quotes are required any time you need a " in a normal script block. #> - + param( - $ProgramsToInstall, - $manage = "Installing" + $ProgramsToInstall, + $manage = "Installing" ) - + $x = 0 - $count = $($ProgramsToInstall -split ",").Count - + $count = $ProgramsToInstall.Count + Write-Progress -Activity "$manage Applications" -Status "Starting" -PercentComplete 0 - - Foreach ($Program in $($ProgramsToInstall -split ",")){ - - Write-Progress -Activity "$manage Applications" -Status "$manage $Program $($x + 1) of $count" -PercentComplete $($x/$count*100) + Write-Host "===========================================" + Write-Host "-- insstalling 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{ + $chocoStatus = $(Start-Process -FilePath "choco" -ArgumentList "install $($Program.choco) -y" -Wait -PassThru).ExitCode + if($chocoStatus -eq 0){ + Write-Host "$($Program.choco) installed successfully using Chocolatey." + continue + } else { + Write-Host "Failed to install $($Program.choco) using Chocolatey." + } + Write-Host "Failed to install $($Program.choco)." + } catch { + Write-Host "Failed to install $($Program.choco) due to an error: $_" + } + } + if($manage -eq "Uninstalling"){ + throw "not yet implemented"; + } + $X++ + } + Write-Progress -Activity "$manage Applications" -Status "Finished" -Completed + return; +} +Function Install-WinUtilProgramWinget { + + <# + .SYNOPSIS + Manages the provided programs using Winget + + .PARAMETER ProgramsToInstall + A list of programs to manage + + .PARAMETER manage + The action to perform on the programs, can be either 'Installing' or 'Uninstalling' + + .NOTES + The triple quotes are required any time you need a " in a normal script block. + #> + + param( + $ProgramsToInstall, + $manage = "Installing" + ) + $x = 0 + $count = $ProgramsToInstall.Count + + Write-Progress -Activity "$manage Applications" -Status "Starting" -PercentComplete 0 + Write-Host "===========================================" + Write-Host "-- installing winget packages ---" + Write-Host "===========================================" + Foreach ($Program in $ProgramsToInstall){ + $failedPackages = @() + Write-Progress -Activity "$manage Applications" -Status "$manage $($Program.winget) $($x + 1) of $count" -PercentComplete $($x/$count*100) if($manage -eq "Installing"){ # Install package via ID, if it fails try again with different scope and then with an unelevated prompt. # Since Install-WinGetPackage might not be directly available, we use winget install command as a workaround. # Winget, not all installers honor any of the following: System-wide, User Installs, or Unelevated Prompt OR Silent Install Mode. # This is up to the individual package maintainers to enable these options. Aka. not as clean as Linux Package Managers. + Write-Host "Starting install of $($Program.winget) with winget." try { - $status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $Program --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru).ExitCode + $status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $($Program.winget) --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru).ExitCode if($status -eq 0){ - Write-Host "$Program installed successfully." + Write-Host "$($Program.winget) installed successfully." continue } Write-Host "Attempt with User scope" - $status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $Program --scope user --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru).ExitCode + $status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $($Program.winget) --scope user --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru).ExitCode if($status -eq 0){ - Write-Host "$Program installed successfully with User scope." + Write-Host "$($Program.winget) installed successfully with User scope." continue } Write-Host "Attempt with User prompt" - $userChoice = [System.Windows.MessageBox]::Show("Do you want to attempt $Program installation with specific user credentials? Select 'Yes' to proceed or 'No' to skip.", "User Credential Prompt", [System.Windows.MessageBoxButton]::YesNo) + $userChoice = [System.Windows.MessageBox]::Show("Do you want to attempt $($Program.winget) installation with specific user credentials? Select 'Yes' to proceed or 'No' to skip.", "User Credential Prompt", [System.Windows.MessageBoxButton]::YesNo) if ($userChoice -eq 'Yes') { $getcreds = Get-Credential - $process = Start-Process -FilePath "winget" -ArgumentList "install --id $Program --silent --accept-source-agreements --accept-package-agreements" -Credential $getcreds -PassThru + $process = Start-Process -FilePath "winget" -ArgumentList "install --id $($Program.winget) --silent --accept-source-agreements --accept-package-agreements" -Credential $getcreds -PassThru Wait-Process -Id $process.Id $status = $process.ExitCode } else { Write-Host "Skipping installation with specific user credentials." } if($status -eq 0){ - Write-Host "$Program installed successfully with User prompt." + Write-Host "$($Program.winget) installed successfully with User prompt." continue } - Write-Host "Attempting installation with Chocolatey as a fallback method" - Install-WinUtilChoco - $status = $(Start-Process -FilePath "choco" -ArgumentList "install $Program -y" -Wait -PassThru).ExitCode - if($status -eq 0){ - Write-Host "$Program installed successfully using Chocolatey." - continue - } - Write-Host "Failed to install $Program. You need to install it manually... Sorry!" - } catch { - Write-Host "Failed to install $Program due to an error: $_" - } + } catch { + Write-Host "Failed to install $($Program.winget). With winget" + $failedPackages += $($Program.winget) + } } if($manage -eq "Uninstalling"){ # Uninstall package via ID using winget directly. try { - $status = $(Start-Process -FilePath "winget" -ArgumentList "uninstall --id $Program --silent" -Wait -PassThru).ExitCode + $status = $(Start-Process -FilePath "winget" -ArgumentList "uninstall --id $($Program.winget) --silent" -Wait -PassThru).ExitCode if($status -ne 0){ - Write-Host "Failed to uninstall $Program." + Write-Host "Failed to uninstall $($Program.winget)." } else { - Write-Host "$Program uninstalled successfully." + Write-Host "$($Program.winget) uninstalled successfully." + $failedPackages += $($Program.winget) } } catch { - Write-Host "Failed to uninstall $Program due to an error: $_" + Write-Host "Failed to uninstall $($Program.winget) due to an error: $_" + $failedPackages += $($Program.winget) } } $X++ } - Write-Progress -Activity "$manage Applications" -Status "Finished" -Completed + return $failedPackages; } function Install-WinUtilWinget { <# @@ -3728,23 +3775,43 @@ function Invoke-WPFInstall { return } - $WingetInstall = (Get-WinUtilCheckBoxes)["Install"] - - if ($wingetinstall.Count -eq 0) { + $PackagesToInstall = (Get-WinUtilCheckBoxes)["Install"] + Write-Host $PackagesToInstall + if ($PackagesToInstall.Count -eq 0) { $WarningMsg = "Please select the program(s) to install or upgrade" [System.Windows.MessageBox]::Show($WarningMsg, $AppTitle, [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } - Invoke-WPFRunspace -ArgumentList $WingetInstall -DebugPreference $DebugPreference -ScriptBlock { - param($WingetInstall, $DebugPreference) + Invoke-WPFRunspace -ArgumentList $PackagesToInstall -DebugPreference $DebugPreference -ScriptBlock { + param($PackagesToInstall, $DebugPreference) + $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 install" + } else { + $packagesWinget.add($package) + Write-Host "Queueing $($package.winget) for Winget install" + } + } + return $packagesWinget, $packagesChoco + }.Invoke($PackagesToInstall) try{ $sync.ProcessRunning = $true - - Install-WinUtilWinget - Install-WinUtilProgramWinget -ProgramsToInstall $WingetInstall - + $errorPackages = @() + if($packagesWinget.Count -gt 0){ + Install-WinUtilWinget + $errorPackages += Install-WinUtilProgramWinget -ProgramsToInstall $packagesWinget + $errorPackages| ForEach-Object {if($_.choco -ne "na") {$packagesChoco += $_}} + } + if($packagesChoco.Count -gt 0){ + Install-WinUtilChoco + Install-WinUtilProgramChoco -ProgramsToInstall $packagesChoco + } Write-Host "===========================================" Write-Host "-- Installs have finished ---" Write-Host "===========================================" @@ -4953,9 +5020,9 @@ function Invoke-WPFUnInstall { return } - $WingetInstall = (Get-WinUtilCheckBoxes)["Install"] + $PackagesToInstall = (Get-WinUtilCheckBoxes)["Install"] - if ($wingetinstall.Count -eq 0) { + if ($PackagesToInstall.Count -eq 0) { $WarningMsg = "Please select the program(s) to install" [System.Windows.MessageBox]::Show($WarningMsg, $AppTitle, [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return @@ -4963,21 +5030,39 @@ function Invoke-WPFUnInstall { $ButtonType = [System.Windows.MessageBoxButton]::YesNo $MessageboxTitle = "Are you sure?" - $Messageboxbody = ("This will uninstall the following applications: `n $WingetInstall") + $Messageboxbody = ("This will uninstall the following applications: `n $($PackagesToInstall | Format-Table | Out-String)") $MessageIcon = [System.Windows.MessageBoxImage]::Information $confirm = [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) if($confirm -eq "No"){return} - Invoke-WPFRunspace -ArgumentList $WingetInstall -DebugPreference $DebugPreference -ScriptBlock { - param($WingetInstall, $DebugPreference) - + Invoke-WPFRunspace -ArgumentList $PackagesToInstall -DebugPreference $DebugPreference -ScriptBlock { + param($PackagesToInstall, $DebugPreference) + $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" + } else { + $packagesWinget.add($package) + Write-Host "Queueing $($package.winget) for Winget Uninstall" + } + } + return $packagesWinget, $packagesChoco + }.Invoke($PackagesToInstall) try{ $sync.ProcessRunning = $true # Install all selected programs in new window - Install-WinUtilProgramWinget -ProgramsToInstall $WingetInstall -Manage "Uninstalling" + if($packagesWinget.Count -gt 0){ + Install-WinUtilProgramWinget -ProgramsToInstall $PackagesToInstall -Manage "Uninstalling" + } + if($packagesChoco.Count -gt 0){ + Install-WinUtilProgramChoco -ProgramsToInstall $PackagesToInstall -Manage "Uninstalling" + } $ButtonType = [System.Windows.MessageBoxButton]::OK $MessageboxTitle = "Uninstalls are Finished "