mqsft.powershell.psm1

# ==============================================================================
# mqsft.powershell.psm1 - AUTO-GENERATED by Create_Module_0_0_3.ps1 v0.0.3
# ------------------------------------------------------------------------------
# Module Version : 1.0.3
# Script Version : 0.0.3
# Built : 2026-02-24 16:43:36
# Source : C:\Modules\functions\mqsft.powershell
#
# DO NOT EDIT THIS FILE DIRECTLY.
# Edit source files in C:\Modules\functions\mqsft.powershell and re-run Create_Module_0_0_3.ps1.
# ==============================================================================

Set-StrictMode -Version Latest

# --- Source: Install-PowerShellVersion.ps1 -------------------------------
function Install-PowerShellVersion {

    <#

    .SYNOPSIS

        GUI-based PowerShell version installer with multiple installation methods

    

    .DESCRIPTION

        Displays a GUI to select and install different PowerShell versions.

        Shows currently installed versions and tries multiple installation methods.

    

    .EXAMPLE

        Install-PowerShellVersion

    #>


    

    [CmdletBinding()]

    param()

    

    Add-Type -AssemblyName System.Windows.Forms

    Add-Type -AssemblyName System.Drawing



    # Available PowerShell versions

    $AvailableVersions = @{

        "PowerShell 7.4 (Latest)" = @{

            Version = "7.4.6"

            MSIUrl = "https://github.com/PowerShell/PowerShell/releases/download/v7.4.6/PowerShell-7.4.6-win-x64.msi"

            WingetId = "Microsoft.PowerShell"

            ChocoId = "powershell-core"

        }

        "PowerShell 7.3" = @{

            Version = "7.3.12"

            MSIUrl = "https://github.com/PowerShell/PowerShell/releases/download/v7.3.12/PowerShell-7.3.12-win-x64.msi"

            WingetId = "Microsoft.PowerShell"

            ChocoId = "powershell-core"

        }

        "PowerShell 7.2 (LTS)" = @{

            Version = "7.2.23"

            MSIUrl = "https://github.com/PowerShell/PowerShell/releases/download/v7.2.23/PowerShell-7.2.23-win-x64.msi"

            WingetId = "Microsoft.PowerShell"

            ChocoId = "powershell-core"

        }

        "PowerShell 6.2" = @{

            Version = "6.2.7"

            MSIUrl = "https://github.com/PowerShell/PowerShell/releases/download/v6.2.7/PowerShell-6.2.7-win-x64.msi"

            WingetId = "Microsoft.PowerShell"

            ChocoId = "powershell-core"

        }

    }



    # Function to get installed PowerShell versions

    function Get-InstalledPowerShellVersions {

        $installed = @()

        

        # Check for pwsh.exe in common locations

        $pwshPaths = @(

            "$env:ProgramFiles\PowerShell\7\pwsh.exe",

            "$env:ProgramFiles\PowerShell\6\pwsh.exe",

            "${env:ProgramFiles(x86)}\PowerShell\7\pwsh.exe",

            "${env:ProgramFiles(x86)}\PowerShell\6\pwsh.exe"

        )

        

        foreach ($path in $pwshPaths) {

            if (Test-Path $path) {

                try {

                    $versionInfo = & $path --version 2>$null

                    if ($versionInfo) {

                        $installed += $versionInfo.Trim()

                    }

                } catch {

                    # Ignore errors

                }

            }

        }

        

        # Also check Windows PowerShell

        $installed += "Windows PowerShell $($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)"

        

        return $installed

    }



    # Function to check if a tool is available

    function Test-CommandAvailable {

        param([string]$Command)

        $null -ne (Get-Command $Command -ErrorAction SilentlyContinue)

    }



    # Function to install via MSI

    function Install-ViaMSI {

        param(

            [string]$Url,

            [string]$Version,

            [System.Windows.Forms.ProgressBar]$ProgressBar,

            [System.Windows.Forms.Label]$StatusLabel

        )

        

        try {

            $StatusLabel.Text = "Method 1/3: Downloading MSI installer..."

            $ProgressBar.Value = 10

            

            $msiPath = "$env:TEMP\PowerShell-$Version-win-x64.msi"

            

            # Download MSI

            $webClient = New-Object System.Net.WebClient

            $webClient.DownloadFile($Url, $msiPath)

            

            $StatusLabel.Text = "Installing PowerShell $Version via MSI..."

            $ProgressBar.Value = 40

            

            # Install MSI silently

            $arguments = "/i `"$msiPath`" /qn /norestart ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL=1 ENABLE_PSREMOTING=1 REGISTER_MANIFEST=1"

            $process = Start-Process msiexec.exe -ArgumentList $arguments -Wait -PassThru

            

            $ProgressBar.Value = 70

            

            # Clean up

            Remove-Item $msiPath -Force -ErrorAction SilentlyContinue

            

            if ($process.ExitCode -eq 0) {

                $StatusLabel.Text = "Successfully installed via MSI!"

                return $true

            } else {

                $StatusLabel.Text = "MSI installation failed (Exit code: $($process.ExitCode))"

                return $false

            }

        } catch {

            $StatusLabel.Text = "MSI method failed: $($_.Exception.Message)"

            return $false

        }

    }



    # Function to install via winget

    function Install-ViaWinget {

        param(

            [string]$WingetId,

            [string]$Version,

            [System.Windows.Forms.ProgressBar]$ProgressBar,

            [System.Windows.Forms.Label]$StatusLabel

        )

        

        try {

            if (-not (Test-CommandAvailable "winget")) {

                $StatusLabel.Text = "Winget not available, skipping..."

                return $false

            }

            

            $StatusLabel.Text = "Method 2/3: Installing via winget..."

            $ProgressBar.Value = 40

            

            $process = Start-Process winget -ArgumentList "install --id $WingetId --version $Version --silent --accept-package-agreements --accept-source-agreements" -Wait -PassThru -NoNewWindow

            

            $ProgressBar.Value = 70

            

            if ($process.ExitCode -eq 0) {

                $StatusLabel.Text = "Successfully installed via winget!"

                return $true

            } else {

                $StatusLabel.Text = "Winget installation failed"

                return $false

            }

        } catch {

            $StatusLabel.Text = "Winget method failed: $($_.Exception.Message)"

            return $false

        }

    }



    # Function to install via Chocolatey

    function Install-ViaChocolatey {

        param(

            [string]$ChocoId,

            [string]$Version,

            [System.Windows.Forms.ProgressBar]$ProgressBar,

            [System.Windows.Forms.Label]$StatusLabel

        )

        

        try {

            if (-not (Test-CommandAvailable "choco")) {

                $StatusLabel.Text = "Chocolatey not available, skipping..."

                return $false

            }

            

            $StatusLabel.Text = "Method 3/3: Installing via Chocolatey..."

            $ProgressBar.Value = 40

            

            $process = Start-Process choco -ArgumentList "install $ChocoId --version=$Version -y --force" -Wait -PassThru -NoNewWindow

            

            $ProgressBar.Value = 70

            

            if ($process.ExitCode -eq 0) {

                $StatusLabel.Text = "Successfully installed via Chocolatey!"

                return $true

            } else {

                $StatusLabel.Text = "Chocolatey installation failed"

                return $false

            }

        } catch {

            $StatusLabel.Text = "Chocolatey method failed: $($_.Exception.Message)"

            return $false

        }

    }



    # Create the form

    $form = New-Object System.Windows.Forms.Form

    $form.Text = "PowerShell Version Installer"

    $form.Size = New-Object System.Drawing.Size(500, 450)

    $form.StartPosition = "CenterScreen"

    $form.FormBorderStyle = "FixedDialog"

    $form.MaximizeBox = $false



    # Currently Installed Label

    $installedLabel = New-Object System.Windows.Forms.Label

    $installedLabel.Location = New-Object System.Drawing.Point(10, 10)

    $installedLabel.Size = New-Object System.Drawing.Size(470, 20)

    $installedLabel.Text = "Currently Installed Versions:"

    $installedLabel.Font = New-Object System.Drawing.Font("Segoe UI", 10, [System.Drawing.FontStyle]::Bold)

    $form.Controls.Add($installedLabel)



    # Installed Versions ListBox

    $installedListBox = New-Object System.Windows.Forms.ListBox

    $installedListBox.Location = New-Object System.Drawing.Point(10, 35)

    $installedListBox.Size = New-Object System.Drawing.Size(470, 80)

    $installedListBox.Font = New-Object System.Drawing.Font("Consolas", 9)

    

    $installedVersions = Get-InstalledPowerShellVersions

    foreach ($version in $installedVersions) {

        [void]$installedListBox.Items.Add($version)

    }

    

    $form.Controls.Add($installedListBox)



    # Version Selection Label

    $selectLabel = New-Object System.Windows.Forms.Label

    $selectLabel.Location = New-Object System.Drawing.Point(10, 130)

    $selectLabel.Size = New-Object System.Drawing.Size(470, 20)

    $selectLabel.Text = "Select Version to Install:"

    $selectLabel.Font = New-Object System.Drawing.Font("Segoe UI", 10, [System.Drawing.FontStyle]::Bold)

    $form.Controls.Add($selectLabel)



    # Version Dropdown

    $versionComboBox = New-Object System.Windows.Forms.ComboBox

    $versionComboBox.Location = New-Object System.Drawing.Point(10, 155)

    $versionComboBox.Size = New-Object System.Drawing.Size(470, 25)

    $versionComboBox.DropDownStyle = "DropDownList"

    

    foreach ($version in $AvailableVersions.Keys) {

        [void]$versionComboBox.Items.Add($version)

    }

    $versionComboBox.SelectedIndex = 0

    

    $form.Controls.Add($versionComboBox)



    # Progress Bar

    $progressBar = New-Object System.Windows.Forms.ProgressBar

    $progressBar.Location = New-Object System.Drawing.Point(10, 200)

    $progressBar.Size = New-Object System.Drawing.Size(470, 30)

    $progressBar.Style = "Continuous"

    $form.Controls.Add($progressBar)



    # Status Label

    $statusLabel = New-Object System.Windows.Forms.Label

    $statusLabel.Location = New-Object System.Drawing.Point(10, 240)

    $statusLabel.Size = New-Object System.Drawing.Size(470, 60)

    $statusLabel.Text = "Ready to install. Click 'Install' to begin."

    $statusLabel.Font = New-Object System.Drawing.Font("Segoe UI", 9)

    $form.Controls.Add($statusLabel)



    # Install Button

    $installButton = New-Object System.Windows.Forms.Button

    $installButton.Location = New-Object System.Drawing.Point(10, 320)

    $installButton.Size = New-Object System.Drawing.Size(230, 40)

    $installButton.Text = "Install Selected Version"

    $installButton.Font = New-Object System.Drawing.Font("Segoe UI", 10, [System.Drawing.FontStyle]::Bold)

    $installButton.BackColor = [System.Drawing.Color]::FromArgb(0, 120, 215)

    $installButton.ForeColor = [System.Drawing.Color]::White

    

    $installButton.Add_Click({

        $selectedVersion = $versionComboBox.SelectedItem

        if (-not $selectedVersion) {

            [System.Windows.Forms.MessageBox]::Show("Please select a version to install.", "No Selection", "OK", "Warning")

            return

        }

        

        $versionInfo = $AvailableVersions[$selectedVersion]

        $installButton.Enabled = $false

        $refreshButton.Enabled = $false

        $progressBar.Value = 0

        

        $statusLabel.Text = "Starting installation of $selectedVersion..."

        

        # Try installation methods in order

        $installed = $false

        

        # Method 1: MSI Installer

        if (-not $installed) {

            $progressBar.Value = 5

            $installed = Install-ViaMSI -Url $versionInfo.MSIUrl -Version $versionInfo.Version -ProgressBar $progressBar -StatusLabel $statusLabel

        }

        

        # Method 2: Winget

        if (-not $installed) {

            $progressBar.Value = 35

            $installed = Install-ViaWinget -WingetId $versionInfo.WingetId -Version $versionInfo.Version -ProgressBar $progressBar -StatusLabel $statusLabel

        }

        

        # Method 3: Chocolatey

        if (-not $installed) {

            $progressBar.Value = 65

            $installed = Install-ViaChocolatey -ChocoId $versionInfo.ChocoId -Version $versionInfo.Version -ProgressBar $progressBar -StatusLabel $statusLabel

        }

        

        if ($installed) {

            $progressBar.Value = 100

            $statusLabel.Text = "Installation complete! Refreshing installed versions..."

            

            # Refresh installed versions

            Start-Sleep -Seconds 2

            $installedListBox.Items.Clear()

            $newVersions = Get-InstalledPowerShellVersions

            foreach ($version in $newVersions) {

                [void]$installedListBox.Items.Add($version)

            }

            

            [System.Windows.Forms.MessageBox]::Show("PowerShell $($versionInfo.Version) installed successfully!`n`nYou may need to restart your terminal to use the new version.", "Installation Complete", "OK", "Information")

        } else {

            $progressBar.Value = 0

            $statusLabel.Text = "All installation methods failed. Please check your internet connection or try manual installation."

            [System.Windows.Forms.MessageBox]::Show("Failed to install PowerShell. All methods failed.`n`nPlease check the status message for details.", "Installation Failed", "OK", "Error")

        }

        

        $installButton.Enabled = $true

        $refreshButton.Enabled = $true

    })

    

    $form.Controls.Add($installButton)



    # Refresh Button

    $refreshButton = New-Object System.Windows.Forms.Button

    $refreshButton.Location = New-Object System.Drawing.Point(250, 320)

    $refreshButton.Size = New-Object System.Drawing.Size(230, 40)

    $refreshButton.Text = "Refresh Installed Versions"

    $refreshButton.Font = New-Object System.Drawing.Font("Segoe UI", 10)

    

    $refreshButton.Add_Click({

        $installedListBox.Items.Clear()

        $versions = Get-InstalledPowerShellVersions

        foreach ($version in $versions) {

            [void]$installedListBox.Items.Add($version)

        }

        $statusLabel.Text = "Refreshed installed versions list."

    })

    

    $form.Controls.Add($refreshButton)



    # Close Button

    $closeButton = New-Object System.Windows.Forms.Button

    $closeButton.Location = New-Object System.Drawing.Point(10, 370)

    $closeButton.Size = New-Object System.Drawing.Size(470, 30)

    $closeButton.Text = "Close"

    $closeButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel

    $form.Controls.Add($closeButton)

    

    $form.CancelButton = $closeButton



    # Show the form

    [void]$form.ShowDialog()

}



# Export the function

# Export-ModuleMember -Function Install-PowerShellVersion

Install-PowerShellVersion
# --- Source: Load-Powershell_7.ps1 ---------------------------------------
Function Load-Powershell_7{

    function New-OutOfProcRunspace {
        param($ProcessId)

        $connectionInfo = New-Object -TypeName System.Management.Automation.Runspaces.NamedPipeConnectionInfo -ArgumentList @($ProcessId)

        $TypeTable = [System.Management.Automation.Runspaces.TypeTable]::LoadDefaultTypeFiles()

        #$Runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateOutOfProcessRunspace($connectionInfo,$Host,$TypeTable)
        $Runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($connectionInfo,$Host,$TypeTable)

        $Runspace.Open()
        $Runspace
    }

    $Process = Start-Process PWSH -ArgumentList @("-NoExit") -PassThru -WindowStyle Hidden

    $Runspace = New-OutOfProcRunspace -ProcessId $Process.Id

    $Host.PushRunspace($Runspace)
}
Load-Powershell_7