From a25c7efef89c7feba0f12605d73891f28288ed8c Mon Sep 17 00:00:00 2001 From: Cryostrixx Date: Mon, 14 Oct 2024 11:36:39 -0700 Subject: [PATCH] Fix CTT PowerShell Profile uninstallation by saving the profile's file hash to the disk if it doesn't exist at uninstall time --- .../Invoke-WinUtilInstallPSProfile.ps1 | 71 ++++-- .../Invoke-WinUtilUninstallPSProfile.ps1 | 224 ++++++++++++------ 2 files changed, 202 insertions(+), 93 deletions(-) diff --git a/functions/private/Invoke-WinUtilInstallPSProfile.ps1 b/functions/private/Invoke-WinUtilInstallPSProfile.ps1 index 77dce2c9..8467feb7 100644 --- a/functions/private/Invoke-WinUtilInstallPSProfile.ps1 +++ b/functions/private/Invoke-WinUtilInstallPSProfile.ps1 @@ -1,68 +1,103 @@ function Invoke-WinUtilInstallPSProfile { <# .SYNOPSIS - Backs up your original profile then installs and applies the CTT PowerShell profile + Backs up your original profile then installs and applies the CTT PowerShell profile. #> Invoke-WPFRunspace -ArgumentList $PROFILE -DebugPreference $DebugPreference -ScriptBlock { + # Remap the automatic built-in $PROFILE variable to the parameter named $PSProfile. param ($PSProfile) + function Invoke-PSSetup { + # Define the URL used to download Chris Titus Tech's PowerShell profile. $url = "https://raw.githubusercontent.com/ChrisTitusTech/powershell-profile/main/Microsoft.PowerShell_profile.ps1" + + # Get the file hash for the user's current PowerShell profile. $OldHash = Get-FileHash $PSProfile -ErrorAction SilentlyContinue + + # Download Chris Titus Tech's PowerShell profile to the 'TEMP' folder. Invoke-RestMethod $url -OutFile "$env:TEMP/Microsoft.PowerShell_profile.ps1" + + # Get the file hash for Chris Titus Tech's PowerShell profile. $NewHash = Get-FileHash "$env:TEMP/Microsoft.PowerShell_profile.ps1" + + # Store the file hash of Chris Titus Tech's PowerShell profile. if (!(Test-Path "$PSProfile.hash")) { $NewHash.Hash | Out-File "$PSProfile.hash" } + # Check if the new profile's hash doesn't match the old profile's hash. if ($NewHash.Hash -ne $OldHash.Hash) { + # Check if oldprofile.ps1 exists and use it as a profile backup source. if (Test-Path "$env:USERPROFILE\oldprofile.ps1") { Write-Host "===> Backup File Exists... <===" -ForegroundColor Yellow Write-Host "===> Moving Backup File... <===" -ForegroundColor Yellow Copy-Item "$env:USERPROFILE\oldprofile.ps1" "$PSProfile.bak" Write-Host "===> Profile Backup: Done. <===" -ForegroundColor Yellow } else { + # If oldprofile.ps1 does not exist use $PSProfile as a profile backup source. + # Check if the profile backup file has not already been created on the disk. if ((Test-Path $PSProfile) -and (-not (Test-Path "$PSProfile.bak"))) { + # Let the user know their PowerShell profile is being backed up. Write-Host "===> Backing Up Profile... <===" -ForegroundColor Yellow + + # Copy the user's current PowerShell profile to the backup file path. Copy-Item -Path $PSProfile -Destination "$PSProfile.bak" + + # Let the user know the profile backup has been completed successfully. Write-Host "===> Profile Backup: Done. <===" -ForegroundColor Yellow } } + # Let the user know Chris Titus Tech's PowerShell profile is being installed. Write-Host "===> Installing Profile... <===" -ForegroundColor Yellow - # Starting new hidden shell process because setup does not work in a runspace + + # Start a new hidden PowerShell instance because setup.ps1 does not work in runspaces. Start-Process -FilePath "pwsh" -ArgumentList "-ExecutionPolicy Bypass -NoProfile -Command `"Invoke-Expression (Invoke-WebRequest `'https://github.com/ChrisTitusTech/powershell-profile/raw/main/setup.ps1`')`"" -WindowStyle Hidden -Wait + + # Let the user know Chris Titus Tech's PowerShell profile has been installed successfully. Write-Host "Profile has been installed. Please restart your shell to reflect the changes!" -ForegroundColor Magenta + + # Let the user know Chris Titus Tech's PowerShell profile has been setup successfully. Write-Host "===> Finished Profile Setup <===" -ForegroundColor Yellow } else { + # Let the user know Chris Titus Tech's PowerShell profile is already fully up-to-date. Write-Host "Profile is up to date" -ForegroundColor Magenta } } + # Check if PowerShell Core is currently installed as a program on the user's system. if (Get-Command "pwsh" -ErrorAction SilentlyContinue) { + # Check if the version of PowerShell Core currently in use is version 7 or higher. if ($PSVersionTable.PSVersion.Major -ge 7) { + # Invoke the PowerShell Profile setup script to install Chris Titus Tech's PowerShell Profile. Invoke-PSSetup - } - else { - Write-Host "Profile requires Powershell 7, which is currently installed but not used!" -ForegroundColor Red - # Load the necessary assembly for Windows Forms - Add-Type -AssemblyName System.Windows.Forms - # Display the Yes/No message box - $question = [System.Windows.Forms.MessageBox]::Show("Profile requires Powershell 7, which is currently installed but not used! Do you want to install Profile for Powershell 7?", "Question", - [System.Windows.Forms.MessageBoxButtons]::YesNo, - [System.Windows.Forms.MessageBoxIcon]::Question) + } else { + # Let the user know that PowerShell 7 is installed but is not currently in use. + Write-Host "This profile requires Powershell 7, which is currently installed but not used!" -ForegroundColor Red - # Check the result + # Load the necessary .NET library required to use Windows Forms to show dialog boxes. + Add-Type -AssemblyName System.Windows.Forms + + # Display the message box asking if the user wants to install PowerShell 7 or not. + $question = [System.Windows.Forms.MessageBox]::Show( + "Profile requires Powershell 7, which is currently installed but not used! Do you want to install the profile for Powershell 7?", + "Question", + [System.Windows.Forms.MessageBoxButtons]::YesNo, + [System.Windows.Forms.MessageBoxIcon]::Question + ) + + # Proceed with the installation and setup of the profile as the user pressed the 'Yes' button. if ($question -eq [System.Windows.Forms.DialogResult]::Yes) { Invoke-PSSetup - } - else { + } else { + # Let the user know the setup of the profile will not proceed as they pressed the 'No' button. Write-Host "Not proceeding with the profile setup!" -ForegroundColor Magenta } } - } - else { - Write-Host "Profile requires Powershell 7, which is not installed!" -ForegroundColor Red + } else { + # Let the user know that the profile requires PowerShell Core but it is not currently installed. + Write-Host "This profile requires Powershell Core, which is currently not installed!" -ForegroundColor Red } } -} +} \ No newline at end of file diff --git a/functions/private/Invoke-WinUtilUninstallPSProfile.ps1 b/functions/private/Invoke-WinUtilUninstallPSProfile.ps1 index ffc91236..7969c1bb 100644 --- a/functions/private/Invoke-WinUtilUninstallPSProfile.ps1 +++ b/functions/private/Invoke-WinUtilUninstallPSProfile.ps1 @@ -1,117 +1,191 @@ function Invoke-WinUtilUninstallPSProfile { <# .SYNOPSIS - # Uninstalls the CTT PowerShell profile then restores the original profile + # Uninstalls the CTT PowerShell profile then restores the original profile. #> Invoke-WPFRunspace -ArgumentList $PROFILE -DebugPreference $DebugPreference -ScriptBlock { + # Remap the automatic built-in $PROFILE variable to the parameter named $PSProfile. param ($PSProfile) - # Function to uninstall Nerd Fonts + # Helper function used to uninstall a specific Nerd Fonts font package. function Uninstall-NerdFonts { + # Define the parameters block for the Uninstall-NerdFonts function. param ( [string]$FontsPath = "$env:LOCALAPPDATA\Microsoft\Windows\Fonts", [string]$FontFamilyName = "CaskaydiaCoveNerdFont" ) + # Get the list of installed fonts as specified by the FontFamilyName parameter. $Fonts = Get-ChildItem $FontsPath -Recurse -Filter "*.ttf" | Where-Object { $_.Name -match $FontFamilyName } + + # Check if the specified fonts are currently installed on the system. if ($Fonts) { + # Let the user know that the Nerd Fonts are currently being uninstalled. Write-Host "===> Uninstalling: Nerd Fonts... <===" -ForegroundColor Yellow + + # Loop over the font files and remove each installed font file one-by-one. $Fonts | ForEach-Object { + # Check if the font file exists on the disk before attempting to remove it. if (Test-Path "$($_.FullName)") { + # Remove the found font files from the disk; uninstalling the font. Remove-Item "$($_.FullName)" } } - } else { - Write-Host "===> Already Uninstalled: Nerd Fonts. <===" -ForegroundColor Yellow + } + + # Let the user know that the Nerd Fonts package has been uninstalled from the system. + if (-not $Fonts) { + Write-Host "===> Successfully Uninstalled: Nerd Fonts. <===" -ForegroundColor Yellow } } - # Check if profile is installed - $PSProfileHash = Get-Content "$PSProfile.hash" - if ((Get-FileHash $PSProfile).Hash -eq $PSProfileHash) { - # Uninstall OhMyPosh - try { - $PSProfileContent = Get-Content "$PSProfile.bak" - $OhMyPoshInUse = $PSProfileContent -match "oh-my-posh init" - if (-not $OhMyPoshInUse) { - if (Get-Command oh-my-posh -ErrorAction SilentlyContinue) { - Write-Host "===> Uninstalling: OhMyPosh... <===" -ForegroundColor Yellow - winget uninstall -e --id JanDeDobbeleer.OhMyPosh + # Check if Chris Titus Tech's PowerShell profile is currently installed on the system. + if (Test-Path $PSProfile -PathType Leaf) { + # Get the file hash for Chris Titus Tech's PowerShell profile and store the returned hash. + $CurrentHash = Get-FileHash $PSProfile + + # Store the file hash of Chris Titus Tech's PowerShell profile and save it to disk. + if (!(Test-Path "$PSProfile.hash")) { + $CurrentHash.Hash | Out-File "$PSProfile.hash" + } + + # Get the file hash of Chris Titus Tech's PowerShell profile and store the returned value. + $PSProfileHash = Get-Content "$PSProfile.hash" + + # Check if Chris Titus Tech's PowerShell profile file hash matches the one that was stored. + if ((Get-FileHash $PSProfile).Hash -eq $PSProfileHash) { + try { + # Get the content of the backup PowerShell profile and store it in-memory. + $PSProfileContent = Get-Content "$PSProfile.bak" + + # Store the flag used to check if OhMyPosh is in use by the backup PowerShell profile. + $OhMyPoshInUse = $PSProfileContent -match "oh-my-posh init" + + # Check if OhMyPosh is not currently in use by the backup PowerShell profile. + if (-not $OhMyPoshInUse) { + # If OhMyPosh is currently installed attempt to uninstall it from the system. + if (Get-Command oh-my-posh -ErrorAction SilentlyContinue) { + # Let the user know that OhMyPosh is currently being uninstalled from their system. + Write-Host "===> Uninstalling: OhMyPosh... <===" -ForegroundColor Yellow + + # Attempt to uninstall OhMyPosh from the system with the WinGet package manager. + winget uninstall -e --id JanDeDobbeleer.OhMyPosh + } + } else { + # Let the user know that the uninstallation of OhMyPosh has been skipped because it is in use. + Write-Host "===> Skipped Uninstall: OhMyPosh In-Use. <===" -ForegroundColor Yellow } - } else { - Write-Host "===> Skipped Uninstall: OhMyPosh In-Use. <===" -ForegroundColor Yellow + } catch { + # Let the user know that an error was encountered when uninstalling OhMyPosh. + Write-Error "Failed to uninstall OhMyPosh. Error: $_" -ForegroundColor Red } - } catch { - Write-Error "Failed to uninstall OhMyPosh. Error: $_" -ForegroundColor Red - } - # Uninstall Nerd Fonts - try { - [string]$FontsPath = "$env:LOCALAPPDATA\Microsoft\Windows\Fonts" - [string]$FontFamilyName = "CaskaydiaCoveNerdFont" - Uninstall-NerdFonts -FontsPath $FontsPath -FontFamilyName $FontFamilyName - } catch { - Write-Error "Failed to uninstall Nerd Fonts. Error: $_" -ForegroundColor Red - } + # Attempt to uninstall the specified Nerd Fonts package from the system. + try { + # Specify the directory that the specified font package will be uninstalled from. + [string]$FontsPath = "$env:LOCALAPPDATA\Microsoft\Windows\Fonts" - # Uninstall Terminal-Icons - try { - $PSProfileContent = Get-Content "$PSProfile.bak" - $TerminalIconsInUse = $PSProfileContent -match "Import-Module" -and $PSProfileContent -match "Terminal-Icons" - if (-not $TerminalIconsInUse) { - if (Get-Module -ListAvailable Terminal-Icons) { - Write-Host "===> Uninstalling: Terminal-Icons... <===" -ForegroundColor Yellow - Uninstall-Module -Name Terminal-Icons + # Specify the name of the font package that is to be uninstalled from the system. + [string]$FontFamilyName = "CaskaydiaCoveNerdFont" + + # Call the function used to uninstall the specified Nerd Fonts package from the system. + Uninstall-NerdFonts -FontsPath $FontsPath -FontFamilyName $FontFamilyName + } catch { + # Let the user know that an error was encountered when uninstalling Nerd Fonts. + Write-Error "Failed to uninstall Nerd Fonts. Error: $_" -ForegroundColor Red + } + + # Attempt to uninstall the Terminal-Icons PowerShell module from the system. + try { + # Get the content of the backup PowerShell profile and store it in-memory. + $PSProfileContent = Get-Content "$PSProfile.bak" + + # Store the flag used to check if Terminal-Icons is in use by the backup PowerShell profile. + $TerminalIconsInUse = $PSProfileContent -match "Import-Module" -and $PSProfileContent -match "Terminal-Icons" + + # Check if Terminal-Icons is not currently in use by the backup PowerShell profile. + if (-not $TerminalIconsInUse) { + # If Terminal-Icons is currently installed attempt to uninstall it from the system. + if (Get-Module -ListAvailable Terminal-Icons) { + # Let the user know that Terminal-Icons is currently being uninstalled from their system. + Write-Host "===> Uninstalling: Terminal-Icons... <===" -ForegroundColor Yellow + + # Attempt to uninstall Terminal-Icons from the system with Uninstall-Module. + Uninstall-Module -Name Terminal-Icons + } + } else { + # Let the user know that the uninstallation of Terminal-Icons has been skipped because it is in use. + Write-Host "===> Skipped Uninstall: Terminal-Icons In-Use. <===" -ForegroundColor Yellow } - } else { - Write-Host "===> Skipped Uninstall: Terminal-Icons In-Use. <===" -ForegroundColor Yellow + } catch { + # Let the user know that an error was encountered when uninstalling Terminal-Icons. + Write-Error "Failed to uninstall Terminal-Icons. Error: $_" -ForegroundColor Red } - } catch { - Write-Error "Failed to uninstall Terminal-Icons. Error: $_" -ForegroundColor Red - } - # Uninstall Zoxide - try { - $PSProfileContent = Get-Content "$PSProfile.bak" - $ZoxideInUse = $PSProfileContent -match "zoxide init" - if (-not $ZoxideInUse) { - if (Get-Command zoxide -ErrorAction SilentlyContinue) { - Write-Host "===> Uninstalling: Zoxide... <===" -ForegroundColor Yellow - winget uninstall -e --id ajeetdsouza.zoxide + # Attempt to uninstall the Zoxide application from the system. + try { + # Get the content of the backup PowerShell profile and store it in-memory. + $PSProfileContent = Get-Content "$PSProfile.bak" + + # Store the flag used to check if Zoxide is in use by the backup PowerShell profile. + $ZoxideInUse = $PSProfileContent -match "zoxide init" + + # Check if Zoxide is not currently in use by the backup PowerShell profile. + if (-not $ZoxideInUse) { + # If Zoxide is currently installed attempt to uninstall it from the system. + if (Get-Command zoxide -ErrorAction SilentlyContinue) { + # Let the user know that Zoxide is currently being uninstalled from their system. + Write-Host "===> Uninstalling: Zoxide... <===" -ForegroundColor Yellow + + # Attempt to uninstall Zoxide from the system with the WinGet package manager. + winget uninstall -e --id ajeetdsouza.zoxide + } + } else { + # Let the user know that the uninstallation of Zoxide been skipped because it is in use. + Write-Host "===> Skipped Uninstall: Zoxide In-Use. <===" -ForegroundColor Yellow } - } else { - Write-Host "===> Skipped Uninstall: Zoxide In-Use. <===" -ForegroundColor Yellow + } catch { + # Let the user know that an error was encountered when uninstalling Zoxide. + Write-Error "Failed to uninstall Zoxide. Error: $_" -ForegroundColor Red } - } catch { - Write-Error "Failed to uninstall Zoxide. Error: $_" -ForegroundColor Red - } - # Uninstall CTT PowerShell profile - try { - Remove-Item $PSProfile - Write-Host "Profile has been uninstalled. Please restart your shell to reflect the changes!" -ForegroundColor Magenta - } catch { - Write-Error "Failed to uninstall profile. Error: $_" -ForegroundColor Red - } + # Attempt to uninstall the CTT PowerShell profile from the system. + try { + # Try and remove the CTT PowerShell Profile file from the disk with Remove-Item. + Remove-Item $PSProfile - # Restore PowerShell profile backup - try { - if (Test-Path "$PSProfile.bak") { - Move-Item "$PSProfile.bak" $PSProfile - Write-Host "===> Restored Profile Backup. <===" -ForegroundColor Yellow + # Let the user know that the CTT PowerShell profile has been uninstalled from the system. + Write-Host "Profile has been uninstalled. Please restart your shell to reflect the changes!" -ForegroundColor Magenta + } catch { + # Let the user know that an error was encountered when uninstalling the profile. + Write-Error "Failed to uninstall profile. Error: $_" -ForegroundColor Red } - } catch { - Write-Error "Failed to restore profile backup. Error: $_" -ForegroundColor Red + + # Attempt to move the user's original PowerShell profile backup back to its original location. + try { + # Check if the backup PowerShell profile exists before attempting to restore the backup. + if (Test-Path "$PSProfile.bak") { + # Restore the backup PowerShell profile and move it to its original location. + Move-Item "$PSProfile.bak" $PSProfile + + # Let the user know that their PowerShell profile backup has been successfully restored. + Write-Host "===> Restored Profile Backup. <===" -ForegroundColor Yellow + } + } catch { + # Let the user know that an error was encountered when restoring the profile backup. + Write-Error "Failed to restore profile backup. Error: $_" -ForegroundColor Red + } + + # Silently cleanup the oldprofile.ps1 file that was created when the CTT PowerShell profile was installed. + Remove-Item "$env:USERPROFILE\oldprofile.ps1" | Out-Null + + # Silently cleanup the file storing the file hash of the CTT PowerShell profile. + Remove-Item "$PSProfile.hash" | Out-Null } - - # Silently cleanup oldprofile.ps1 script - Remove-Item "$env:USERPROFILE\oldprofile.ps1" | Out-Null - - # Silently cleanup $PSProfile.hash file - Remove-Item "$PSProfile.hash" | Out-Null } else { - Write-Host "===> Already Uninstalled CTT PowerShell Profile. <===" -ForegroundColor Magenta + # Let the user know that no PowerShell profile was found and that the uninstallation was skipped. + Write-Host "===> No PowerShell Profile Found. Skipped Uninstallation. <===" -ForegroundColor Magenta } } } \ No newline at end of file