diff --git a/config/feature.json b/config/feature.json index 7ea9e48c..9405cb33 100644 --- a/config/feature.json +++ b/config/feature.json @@ -306,13 +306,23 @@ "ButtonWidth": "300", "link": "https://christitustech.github.io/winutil/dev/features/Legacy-Windows-Panels/user" }, - "WPFWinUtilPSProfile": { + "WPFWinUtilInstallPSProfile": { "Content": "Install CTT PowerShell Profile", "category": "Powershell Profile", "panel": "2", "Order": "a083_", "Type": "Button", - "ButtonWidth": "300" + "ButtonWidth": "300", + "link": "https://christitustech.github.io/winutil/dev/features/Powershell-Profile/PSProfileInstall" + }, + "WPFWinUtilUninstallPSProfile": { + "Content": "Uninstall CTT PowerShell Profile", + "category": "Powershell Profile", + "panel": "2", + "Order": "a084_", + "Type": "Button", + "ButtonWidth": "300", + "link": "https://christitustech.github.io/winutil/dev/features/Powershell-Profile/PSProfileUninstall" }, "WPFWinUtilSSHServer": { "Content": "Enable OpenSSH Server", @@ -322,4 +332,4 @@ "Type": "Button", "ButtonWidth": "300" } -} +} \ No newline at end of file diff --git a/docs/dev/features/PowerShell-Profile/PSProfileInstall.md b/docs/dev/features/PowerShell-Profile/PSProfileInstall.md new file mode 100644 index 00000000..6d2d12d4 --- /dev/null +++ b/docs/dev/features/PowerShell-Profile/PSProfileInstall.md @@ -0,0 +1,38 @@ +# Install CTT PowerShell Profile + +Last Updated: 2024-10-01 + + +!!! info + The Development Documentation is auto generated for every compilation of WinUtil, meaning a part of it will always stay up-to-date. **Developers do have the ability to add custom content, which won't be updated automatically.** + + + + + + +
+Preview Code + +```json +{ + "Content": "Install CTT PowerShell Profile", + "category": "Powershell Profile", + "panel": "2", + "Order": "a083_", + "Type": "Button", + "ButtonWidth": "300", + "link": "https://christitustech.github.io/winutil/dev/features/Powershell-Profile/PSProfileInstall" +} +``` + +
+ + + + + + + +[View the JSON file](https://github.com/ChrisTitusTech/winutil/tree/main/config/feature.json) + diff --git a/docs/dev/features/PowerShell-Profile/PSProfileUninstall.md b/docs/dev/features/PowerShell-Profile/PSProfileUninstall.md new file mode 100644 index 00000000..2afc72fa --- /dev/null +++ b/docs/dev/features/PowerShell-Profile/PSProfileUninstall.md @@ -0,0 +1,38 @@ +# Uninstall CTT PowerShell Profile + +Last Updated: 2024-10-01 + + +!!! info + The Development Documentation is auto generated for every compilation of WinUtil, meaning a part of it will always stay up-to-date. **Developers do have the ability to add custom content, which won't be updated automatically.** + + + + + + +
+Preview Code + +```json +{ + "Content": "Uninstall CTT PowerShell Profile", + "category": "Powershell Profile", + "panel": "2", + "Order": "a084_", + "Type": "Button", + "ButtonWidth": "300", + "link": "https://christitustech.github.io/winutil/dev/features/Powershell-Profile/PSProfileUninstall" +} +``` + +
+ + + + + + + +[View the JSON file](https://github.com/ChrisTitusTech/winutil/tree/main/config/feature.json) + diff --git a/functions/private/Invoke-WinUtilInstallPSProfile.ps1 b/functions/private/Invoke-WinUtilInstallPSProfile.ps1 new file mode 100644 index 00000000..e34fc75b --- /dev/null +++ b/functions/private/Invoke-WinUtilInstallPSProfile.ps1 @@ -0,0 +1,103 @@ +function Invoke-WinUtilInstallPSProfile { + <# + .SYNOPSIS + 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 + + # 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 and is available as a command. + 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 { + # 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 + + # 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 { + # 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 { + # 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 new file mode 100644 index 00000000..3394fa7c --- /dev/null +++ b/functions/private/Invoke-WinUtilUninstallPSProfile.ps1 @@ -0,0 +1,187 @@ +function Invoke-WinUtilUninstallPSProfile { + <# + .SYNOPSIS + # 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) + + # 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)" + } + } + } + + # 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 Chris Titus Tech's PowerShell profile is currently available in the PowerShell profile folder. + if (Test-Path $PSProfile -PathType Leaf) { + # Set the GitHub repo path used for looking up the name of Chris Titus Tech's powershell-profile repo. + $GitHubRepoPath = "ChrisTitusTech/powershell-profile" + + # Get the unique identifier used to test for the presence of Chris Titus Tech's PowerShell profile. + $PSProfileIdentifier = (Invoke-RestMethod "https://api.github.com/repos/$GitHubRepoPath").full_name + + # Check if Chris Titus Tech's PowerShell profile is currently installed in the PowerShell profile folder. + if ((Get-Content $PSProfile) -match $PSProfileIdentifier) { + # Attempt to uninstall Chris Titus Tech's PowerShell profile from the PowerShell profile folder. + 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 + } + } catch { + # Let the user know that an error was encountered when uninstalling OhMyPosh. + Write-Host "Failed to uninstall OhMyPosh. 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" + + # 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-Host "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 + } + } catch { + # Let the user know that an error was encountered when uninstalling Terminal-Icons. + Write-Host "Failed to uninstall Terminal-Icons. Error: $_" -ForegroundColor Red + } + + # 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 + } + } catch { + # Let the user know that an error was encountered when uninstalling Zoxide. + Write-Host "Failed to uninstall Zoxide. 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 + + # 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-Host "Failed to uninstall profile. 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-Host "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 + } else { + # Let the user know that the CTT PowerShell profile is not installed and that the uninstallation was skipped. + Write-Host "===> Chris Titus Tech's PowerShell Profile Not Found. Skipped Uninstallation. <===" -ForegroundColor Magenta + } + } else { + # 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 diff --git a/functions/public/Invoke-WPFButton.ps1 b/functions/public/Invoke-WPFButton.ps1 index 7fe63d62..8a63e3bb 100644 --- a/functions/public/Invoke-WPFButton.ps1 +++ b/functions/public/Invoke-WPFButton.ps1 @@ -50,13 +50,15 @@ function Invoke-WPFButton { "WPFFixesNetwork" {Invoke-WPFFixesNetwork} "WPFUpdatesdisable" {Invoke-WPFUpdatesdisable} "WPFUpdatessecurity" {Invoke-WPFUpdatessecurity} + "WPFWinUtilShortcut" {Invoke-WPFShortcut -ShortcutToAdd "WinUtil" -RunAsAdmin $true} "WPFGetInstalled" {Invoke-WPFGetInstalled -CheckBox "winget"} "WPFGetInstalledTweaks" {Invoke-WPFGetInstalled -CheckBox "tweaks"} "WPFGetIso" {Invoke-MicrowinGetIso} "WPFMicrowin" {Invoke-Microwin} "WPFCloseButton" {Invoke-WPFCloseButton} "MicrowinScratchDirBT" {Invoke-ScratchDialog} - "WPFWinUtilPSProfile" {Invoke-WinUtilpsProfile} + "WPFWinUtilInstallPSProfile" {Invoke-WinUtilInstallPSProfile} + "WPFWinUtilUninstallPSProfile" {Invoke-WinUtilUninstallPSProfile} "WPFWinUtilSSHServer" {Invoke-WinUtilSSHServer} } }