From 5a98f63657af89e04f8858f60e8efd0c256b650b Mon Sep 17 00:00:00 2001 From: Kian Date: Fri, 10 May 2024 15:18:24 -0500 Subject: [PATCH] Install flow rework Sperated Winget and Chocolatey setps when installing software add skip them when not needed --- functions/private/Get-WinUtilCheckBoxes.ps1 | 12 +-- .../private/Install-WinUtilProgramChoco.ps1 | 52 ++++++++++++ .../private/Install-WinUtilProgramWinget.ps1 | 79 +++++++++---------- functions/public/Invoke-WPFInstall.ps1 | 38 ++++++--- 4 files changed, 123 insertions(+), 58 deletions(-) create mode 100644 functions/private/Install-WinUtilProgramChoco.ps1 diff --git a/functions/private/Get-WinUtilCheckBoxes.ps1 b/functions/private/Get-WinUtilCheckBoxes.ps1 index 2096d1fc..9372fae6 100644 --- a/functions/private/Get-WinUtilCheckBoxes.ps1 +++ b/functions/private/Get-WinUtilCheckBoxes.ps1 @@ -36,19 +36,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" { # Get the winget value - $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 + [PsCustomObject]@{ + winget="$($sync.configs.applications.$($CheckBox.Name).winget)"; + choco="$($sync.configs.applications.$($CheckBox.Name).choco)"; } + } default { $CheckBox.Name @@ -72,6 +69,5 @@ Function Get-WinUtilCheckBoxes { } } } - return $Output } diff --git a/functions/private/Install-WinUtilProgramChoco.ps1 b/functions/private/Install-WinUtilProgramChoco.ps1 new file mode 100644 index 00000000..8271c70c --- /dev/null +++ b/functions/private/Install-WinUtilProgramChoco.ps1 @@ -0,0 +1,52 @@ +function Install-WinUtilProgramChoco { + <# + .SYNOPSIS + Manages the provided programs using Chocolatey + + .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 "-- 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; +} diff --git a/functions/private/Install-WinUtilProgramWinget.ps1 b/functions/private/Install-WinUtilProgramWinget.ps1 index 187bb37c..d26ba9a3 100644 --- a/functions/private/Install-WinUtilProgramWinget.ps1 +++ b/functions/private/Install-WinUtilProgramWinget.ps1 @@ -1,90 +1,87 @@ Function Install-WinUtilProgramWinget { - + <# .SYNOPSIS - Manages the provided programs using Winget - + Manages the provided programs using Winget + .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 "-- 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; } diff --git a/functions/public/Invoke-WPFInstall.ps1 b/functions/public/Invoke-WPFInstall.ps1 index 54d0ed1d..0032f10f 100644 --- a/functions/public/Invoke-WPFInstall.ps1 +++ b/functions/public/Invoke-WPFInstall.ps1 @@ -12,23 +12,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 "==========================================="