winutil/docs/dev/tweaks/Essential-Tweaks/Powershell7.md
MyDrift 5e3c6ba452
[Docs 02] Auto dev-docs & more (#2481)
* Compile Winutil

* pre-Releases (#1)

* Create pre-release.yaml

* Update release.yaml

* Update pre-release.yaml

* Create release-drafter.yml

* Update release-drafter.yml

* Update pre-release.yaml

* Update pre-release.yaml

* Update pre-release.yaml

* Update pre-release.yaml

* Update pre-release.yaml

* Update pre-release.yaml

* Update pre-release.yaml

* Update pre-release.yaml

* Update pre-release.yaml

* Update release-drafter.yml

* Update pre-release.yaml

* Update release-drafter.yml

* Update pre-release.yaml

* Update release-drafter.yml

* Update release-drafter.yml

* Update pre-release.yaml

* Update pre-release.yaml

* Update release-drafter.yml

* Update release-drafter.yml

* Update release.yaml

* Update release-drafter.yml

* Update release-drafter.yml

* Update pre-release.yaml

* Compile Winutil

* fixed end task with right click

* Compile Winutil

* code generator & compile integration

* Compile Winutil

* finish

- add autogenerated table of content page named "Dev Docs", with table of content to all .md files
- added invokescript & undoscript
- generate documentation files

* oops, remove dublicates

* undo winutil.ps1

* remove prefixes

WPF
WinUtil
Toggle
$category
Features
Tweaks
Panel
Fixes

* fixes

- fix inconsistency in Featurenaming
- add "Enable" & "Disable" as prefix to remove

* fix spellin mistake

* remove unneccesary whitespaces

update info
remove unnecessary whitespaces by only adding stuff to the md if it actually exists

* rewrite prefix removal into one line definition

* added taskscheduler support

* add support for function calling

add support for functioncalling
- replace code formatting for invoke & undo script from json to powershell

* content instead of displayname

* add last modified date

* contributing + docs generator

- moved contribute.md to root CONTRIBUTING.md
- referenced CONTRIBUTING.md in contribute.md
- added toggle & button reference to functions
- added function references in functions
- changed mkdocs site styling

* Use HashSet for processedFunctions

Use HashSet for processedFunctions:
- Ensures dynamic addition of functions without duplication.
Recursive Function Scanning:
- Includes all nested functions called by InvokeScript, UndoScript, ToggleScript, and ButtonScript.

* follow github standards

- add code of conduct
- reference code of conduct in docs
- regrouped docs navigation
- add comment about the sourced md file

* small fixes

* change color from teal to blue in light mode

* add links to tweaks

* add archiving feature to autodocs

* administrative

- add script to releases and remove from compile
- move link from after description to after category

* small fixes

- add S in feature.json
- fix dating
- move link to after category

* fix links

* undo link bc of bugs

* add progress bar to script

- add progress like in compile
- moved archive folder creation to the beginning of the script

* Simple improvements to 'auto-devdocs' branch (#3)

* Fix links for tweaks & features

* Make New Line characters work for Json Snippet

* Change NewLine Character from Unix Style (LF) to Windows/DOS Style (CRLF)

* rerun script

* und workflows & rearrange navigation items

* layer out itemname cutout

* rework links & temp removal of archivation

* fix adding link in json root

not adding link member to root in json files

* fix json generation

replace '\r\n',"`r`n" with ('\n',"`n")

* add features to auto md docs

* add minify plugin

* regex hotfix

* refractor

* add changelog to about section

add link to changelog in docs for about section

* undo changelog

* Cleanup 'devdocs-generator.ps1' - Implement Zig Multiline String Feature (#4)

* Cleanup 'devdocs-generator.ps1' - Implement Zig Multiline String Feature

* Fix NewLine character replace in 'devdocs-generator.ps1'

* run script

* run script

* Fix 'itemnametocut' RegEx in 'devdocs-generator.ps1' (#5)

* rerun script

* rework nav + remove code of conduct

* undo workflow changes

* run script

* remove changelog

---------

Co-authored-by: MyDrift-user <MyDrift-user@users.noreply.github.com>
Co-authored-by: Mr.k <mineshtine28546271@gmail.com>
2024-08-07 10:55:23 -05:00

14 KiB

Change Windows Terminal default: PowerShell 5 -> PowerShell 7

Last Updated: 2024-08-07

!!! 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.

Description

This will edit the config file of the Windows Terminal replacing PowerShell 5 with PowerShell 7 and installing PS7 if necessary

Preview Code
{
  "Content": "Change Windows Terminal default: PowerShell 5 -> PowerShell 7",
  "Description": "This will edit the config file of the Windows Terminal replacing PowerShell 5 with PowerShell 7 and installing PS7 if necessary",
  "category": "Essential Tweaks",
  "panel": "1",
  "Order": "a009_",
  "InvokeScript": [
    "Invoke-WPFTweakPS7 -action \"PS7\""
  ],
  "UndoScript": [
    "Invoke-WPFTweakPS7 -action \"PS5\""
  ],
  "link": "https://christitustech.github.io/winutil/dev/tweaks/Essential-Tweaks/Powershell7"
}

Invoke Script

Invoke-WPFTweakPS7 -action "PS7"

Undo Script

Invoke-WPFTweakPS7 -action "PS5"

Function: Invoke-WPFTweakPS7

function Invoke-WPFTweakPS7{
        <#
    .SYNOPSIS
        This will edit the config file of the Windows Terminal Replacing the Powershell 5 to Powershell 7 and install Powershell 7 if necessary
    .PARAMETER action
        PS7:           Configures Powershell 7 to be the default Terminal
        PS5:           Configures Powershell 5 to be the default Terminal
    #>
    param (
        [ValidateSet("PS7", "PS5")]
        [string]$action
    )

    switch ($action) {
        "PS7"{
            if (Test-Path -Path "$env:ProgramFiles\PowerShell\7") {
                Write-Host "Powershell 7 is already installed."
            } else {
                Write-Host "Installing Powershell 7..."
                Invoke-WinUtilWingetProgram -Action Install -Programs @("Microsoft.PowerShell")
            }
            $targetTerminalName = "PowerShell"
        }
        "PS5"{
            $targetTerminalName = "Windows PowerShell"
        }
    }
    # Check if the Windows Terminal is installed and return if not (Prerequisite for the following code)
    if (-not (Get-Command "wt" -ErrorAction SilentlyContinue)) {
        Write-Host "Windows Terminal not installed. Skipping Terminal preference"
        return
    }
    # Check if the Windows Terminal settings.json file exists and return if not (Prereqisite for the following code)
    $settingsPath = "$env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json"
    if (-not (Test-Path -Path $settingsPath)) {
        Write-Host "Windows Terminal Settings file not found at $settingsPath"
        return
    }

    Write-Host "Settings file found."
    $settingsContent = Get-Content -Path $settingsPath | ConvertFrom-Json
    $ps7Profile = $settingsContent.profiles.list | Where-Object { $_.name -eq $targetTerminalName }
    if ($ps7Profile) {
        $settingsContent.defaultProfile = $ps7Profile.guid
        $updatedSettings = $settingsContent | ConvertTo-Json -Depth 100
        Set-Content -Path $settingsPath -Value $updatedSettings
        Write-Host "Default profile updated to " -NoNewline
        Write-Host "$targetTerminalName " -ForegroundColor White -NoNewline
        Write-Host "using the name attribute."
    } else {
        Write-Host "No PowerShell 7 profile found in Windows Terminal settings using the name attribute."
    }
}

Function: Invoke-WinUtilWingetProgram

Function Invoke-WinUtilWingetProgram {
    <#
    .SYNOPSIS
    Runs the designated action on the provided programs using Winget

    .PARAMETER Programs
    A list of programs to process

    .PARAMETER action
    The action to perform on the programs, can be either 'Install' or 'Uninstall'

    .NOTES
    The triple quotes are required any time you need a " in a normal script block.
    The winget Return codes are documented here: https://github.com/microsoft/winget-cli/blob/master/doc/windows/package-actionr/winget/returnCodes.md
    #>

    param(
        [Parameter(Mandatory, Position=0)]$Programs,

        [Parameter(Mandatory, Position=1)]
        [ValidateSet("Install", "Uninstall")]
        [String]$Action
    )

    Function Invoke-Winget {
    <#
    .SYNOPSIS
    Invokes the winget.exe with the provided arguments and return the exit code

    .PARAMETER wingetId
    The Id of the Program that Winget should Install/Uninstall

    .PARAMETER scope
    Determines the installation mode. Can be "user" or "machine" (For more info look at the winget documentation)

    .PARAMETER credential
    The PSCredential Object of the user that should be used to run winget

    .NOTES
    Invoke Winget uses the public variable $Action defined outside the function to determine if a Program should be installed or removed
    #>
        param (
            [string]$wingetId,
            [string]$scope = "",
            [PScredential]$credential = $null
        )

        $commonArguments = "--id $wingetId --silent"
        $arguments = if ($Action -eq "Install") {
            "install $commonArguments --accept-source-agreements --accept-package-agreements $(if ($scope) {" --scope $scope"})"
        } else {
            "uninstall $commonArguments"
        }

        $processParams = @{
            FilePath = "winget"
            ArgumentList = $arguments
            Wait = $true
            PassThru = $true
            NoNewWindow = $true
        }

        if ($credential) {
            $processParams.credential = $credential
        }

        return (Start-Process @processParams).ExitCode
    }

    Function Invoke-Install {
    <#
    .SYNOPSIS
    Contains the Install Logic and return code handling from winget

    .PARAMETER Program
    The Winget ID of the Program that should be installed
    #>
        param (
            [string]$Program
        )
        $status = Invoke-Winget -wingetId $Program
        if ($status -eq 0) {
            Write-Host "$($Program) installed successfully."
            return $true
        } elseif ($status -eq -1978335189) {
            Write-Host "$($Program) No applicable update found"
            return $true
        }

        Write-Host "Attempt installation of $($Program) with User scope"
        $status = Invoke-Winget -wingetId $Program -scope "user"
        if ($status -eq 0) {
            Write-Host "$($Program) installed successfully with User scope."
            return $true
        } elseif ($status -eq -1978335189) {
            Write-Host "$($Program) No applicable update found"
            return $true
        }

        $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)
        if ($userChoice -eq 'Yes') {
            $getcreds = Get-Credential
            $status = Invoke-Winget -wingetId $Program -credential $getcreds
            if ($status -eq 0) {
                Write-Host "$($Program) installed successfully with User prompt."
                return $true
            }
        } else {
            Write-Host "Skipping installation with specific user credentials."
        }

        Write-Host "Failed to install $($Program)."
        return $false
    }

    Function Invoke-Uninstall {
        <#
        .SYNOPSIS
        Contains the Uninstall Logic and return code handling from winget

        .PARAMETER Program
        The Winget ID of the Program that should be uninstalled
        #>
        param (
            [psobject]$Program
        )

        try {
            $status = Invoke-Winget -wingetId $Program
            if ($status -eq 0) {
                Write-Host "$($Program) uninstalled successfully."
                return $true
            } else {
                Write-Host "Failed to uninstall $($Program)."
                return $false
            }
        } catch {
            Write-Host "Failed to uninstall $($Program) due to an error: $_"
            return $false
        }
    }

    $count = $Programs.Count
    $failedPackages = @()

    Write-Host "==========================================="
    Write-Host "--    Configuring winget packages       ---"
    Write-Host "==========================================="

    for ($i = 0; $i -lt $count; $i++) {
        $Program = $Programs[$i]
        $result = $false
        Set-WinUtilProgressBar -label "$Action $($Program)" -percent ($i / $count * 100)
        $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i / $count)})

        $result = switch ($Action) {
            "Install" {Invoke-Install -Program $Program}
            "Uninstall" {Invoke-Uninstall -Program $Program}
            default {throw "[Install-WinUtilProgramWinget] Invalid action: $Action"}
        }

        if (-not $result) {
            $failedPackages += $Program
        }
    }

    Set-WinUtilProgressBar -label "$($Action)ation done" -percent 100
    return $failedPackages
}

Function: Set-WinUtilProgressbar

function Set-WinUtilProgressbar{
    <#
    .SYNOPSIS
        This function is used to Update the Progress Bar displayed in the winutil GUI.
        It will be automatically hidden if the user clicks something and no process is running
    .PARAMETER Label
        The Text to be overlayed onto the Progress Bar
    .PARAMETER PERCENT
        The percentage of the Progress Bar that should be filled (0-100)
    .PARAMETER Hide
        If provided, the Progress Bar and the label will be hidden
    #>
    param(
        [string]$Label,
        [ValidateRange(0,100)]
        [int]$Percent,
        $Hide
    )
    if ($hide) {
        $sync.form.Dispatcher.Invoke([action]{$sync.ProgressBarLabel.Visibility = "Collapsed"})
        $sync.form.Dispatcher.Invoke([action]{$sync.ProgressBar.Visibility = "Collapsed"})
    } else {
        $sync.form.Dispatcher.Invoke([action]{$sync.ProgressBarLabel.Visibility = "Visible"})
        $sync.form.Dispatcher.Invoke([action]{$sync.ProgressBar.Visibility = "Visible"})
    }
    $sync.form.Dispatcher.Invoke([action]{$sync.ProgressBarLabel.Content.Text = $label})
    $sync.form.Dispatcher.Invoke([action]{$sync.ProgressBarLabel.Content.ToolTip = $label})
    $sync.form.Dispatcher.Invoke([action]{ $sync.ProgressBar.Value = $percent})

}

Function: Set-WinUtilTaskbarItem

function Set-WinUtilTaskbaritem {
    <#

    .SYNOPSIS
        Modifies the Taskbaritem of the WPF Form

    .PARAMETER value
        Value can be between 0 and 1, 0 being no progress done yet and 1 being fully completed
        Value does not affect item without setting the state to 'Normal', 'Error' or 'Paused'
        Set-WinUtilTaskbaritem -value 0.5

    .PARAMETER state
        State can be 'None' > No progress, 'Indeterminate' > inf. loading gray, 'Normal' > Gray, 'Error' > Red, 'Paused' > Yellow
        no value needed:
        - Set-WinUtilTaskbaritem -state "None"
        - Set-WinUtilTaskbaritem -state "Indeterminate"
        value needed:
        - Set-WinUtilTaskbaritem -state "Error"
        - Set-WinUtilTaskbaritem -state "Normal"
        - Set-WinUtilTaskbaritem -state "Paused"

    .PARAMETER overlay
        Overlay icon to display on the taskbar item, there are the presets 'None', 'logo' and 'checkmark' or you can specify a path/link to an image file.
        CTT logo preset:
        - Set-WinUtilTaskbaritem -overlay "logo"
        Checkmark preset:
        - Set-WinUtilTaskbaritem -overlay "checkmark"
        Warning preset:
        - Set-WinUtilTaskbaritem -overlay "warning"
        No overlay:
        - Set-WinUtilTaskbaritem -overlay "None"
        Custom icon (needs to be supported by WPF):
        - Set-WinUtilTaskbaritem -overlay "C:\path\to\icon.png"

    .PARAMETER description
        Description to display on the taskbar item preview
        Set-WinUtilTaskbaritem -description "This is a description"
    #>
    param (
        [string]$state,
        [double]$value,
        [string]$overlay,
        [string]$description
    )

    if ($value) {
        $sync["Form"].taskbarItemInfo.ProgressValue = $value
    }

    if ($state) {
        switch ($state) {
            'None' { $sync["Form"].taskbarItemInfo.ProgressState = "None" }
            'Indeterminate' { $sync["Form"].taskbarItemInfo.ProgressState = "Indeterminate" }
            'Normal' { $sync["Form"].taskbarItemInfo.ProgressState = "Normal" }
            'Error' { $sync["Form"].taskbarItemInfo.ProgressState = "Error" }
            'Paused' { $sync["Form"].taskbarItemInfo.ProgressState = "Paused" }
            default { throw "[Set-WinUtilTaskbarItem] Invalid state" }
        }
    }

    if ($overlay) {
        switch ($overlay) {
            'logo' {
                $sync["Form"].taskbarItemInfo.Overlay = "$env:LOCALAPPDATA\winutil\cttlogo.png"
            }
            'checkmark' {
                $sync["Form"].taskbarItemInfo.Overlay = "$env:LOCALAPPDATA\winutil\checkmark.png"
            }
            'warning' {
                $sync["Form"].taskbarItemInfo.Overlay = "$env:LOCALAPPDATA\winutil\warning.png"
            }
            'None' {
                $sync["Form"].taskbarItemInfo.Overlay = $null
            }
            default {
                if (Test-Path $overlay) {
                    $sync["Form"].taskbarItemInfo.Overlay = $overlay
                }
            }
        }
    }

    if ($description) {
        $sync["Form"].taskbarItemInfo.Description = $description
    }
}

View the JSON file