Shell/Public/New-Shell.ps1
|
<#
.SYNOPSIS Opens a new PowerShell or Windows Terminal session with elevated or alternate user context. .DESCRIPTION This function launches a new shell session in various contexts: - Standard or elevated (Administrator) PowerShell/PowerShell Core - As a different user (with credentials) - In Windows Terminal (optionally elevated) If the current session is already elevated, a warning is displayed. Robust error handling using trap statements is included for all launch scenarios. .PARAMETER User Specifies the type of shell to start. Valid values: 'PowerShell' (Windows PowerShell), 'pwsh' (PowerShell Core). .PARAMETER RunAs Launches the shell as Administrator. Valid values: 'PowerShellRunAs', 'pwshRunAs'. .PARAMETER RunAsUser Launches the shell as a different user. Valid values: 'PowerShellRunAsUser', 'pwshRunAsUser'. .PARAMETER Credentials Credentials object for RunAsUser. Mandatory when using RunAsUser. .PARAMETER ForceNewWindow Forces the RunAsUser shell to launch in a dedicated console window, which is useful when invoked from hosts that hide child process windows such as Stream Deck scripts. .PARAMETER ShellArgumentList Provides additional arguments for the shell executable when using RunAsUser. Combine with ForceNewWindow to control the star ted session. .PARAMETER WindowTitle Sets a custom console window title when ForceNewWindow is specified. Defaults to an empty title when omitted. .PARAMETER Terminal Launches the shell in Windows Terminal. Valid values: 'PowerShellTerminal', 'pwshTerminal'. .PARAMETER TerminalRunAs Launches Windows Terminal as Administrator with the specified profile. Valid values: 'PowerShellTerminalRunAs', 'pwshTerminalRunAs'. .EXAMPLE New-Shell -User pwsh # Launches a new PowerShell Core shell. .EXAMPLE New-Shell -RunAs PowerShellRunAs # Launches a new elevated Windows PowerShell shell. .EXAMPLE New-Shell -RunAsUser pwshRunAsUser -Credentials (Get-Credential) # Launches a new PowerShell Core shell as a specified user. .EXAMPLE New-Shell -Terminal pwshTerminal # Launches a new PowerShell Core shell in Windows Terminal. .EXAMPLE New-Shell -TerminalRunAs pwshTerminalRunAs # Launches a new elevated PowerShell Core shell in Windows Terminal. .NOTES Author: RDGScripts Maintainers Date: 2025-09-02 Prerequisites: PowerShell Core (pwsh.exe) and Windows Terminal (wt.exe) must be installed for respective options. Microsoft Docs: - Start-Process: https://learn.microsoft.com/powershell/module/microsoft.powershell.management/start-process - Windows Terminal: https://learn.microsoft.com/windows/terminal/ #> function New-Shell { [CmdletBinding(DefaultParameterSetName = 'User')] [Alias('ns')] param ( [Parameter(ParameterSetName = 'User', Mandatory = $false, Position = 0, HelpMessage = 'Specifies the type of shell to start.')] [ValidateSet('PowerShell', 'pwsh')] [string] $User, [Parameter(ParameterSetName = 'RunAs', Mandatory = $false, Position = 0, HelpMessage = 'Specifies to run the shell as an administrator.')] [ValidateSet('PowerShellRunAs', 'pwshRunAs')] [string] $RunAs, [Parameter(ParameterSetName = 'RunAsUser', Mandatory = $false, Position = 0, HelpMessage = 'Specifies to run the shell as a different user.')] [ValidateSet('PowerShellRunAsUser', 'pwshRunAsUser')] [string] $RunAsUser, [Parameter(ParameterSetName = 'RunAsUser', Mandatory = $true, Position = 1, HelpMessage = 'Specifies the credentials to use for the RunAsUser parameter.')] [ValidateNotNull()] [pscredential] $Credentials, [Parameter(ParameterSetName = 'RunAsUser', Mandatory = $false, HelpMessage = 'Forces the shell to launch in a new window when running as another user.')] [switch] $ForceNewWindow, [Parameter(ParameterSetName = 'RunAsUser', Mandatory = $false, HelpMessage = 'Specifies additional arguments for the shell when running as another user.')] [string[]] $ShellArgumentList, [Parameter(ParameterSetName = 'RunAsUser', Mandatory = $false, HelpMessage = 'Specifies the window title when a new window is launched for another user.')] [string] $WindowTitle, [Parameter(ParameterSetName = 'Terminal', Mandatory = $false, Position = 0, HelpMessage = 'Specifies to launch the shell in Windows Terminal.')] [ValidateSet('PowerShellTerminal', 'pwshTerminal')] [string] $Terminal, [Parameter(ParameterSetName = 'TerminalRunAs', Mandatory = $false, Position = 0, HelpMessage = 'Specifies to run Windows Terminal as an administrator with the specified profile.')] [ValidateSet('PowerShellTerminalRunAs', 'pwshTerminalRunAs')] [string] $TerminalRunAs ) begin { Write-Verbose "Starting New-Shell function with parameter set: $($PSCmdlet.ParameterSetName)" } process { # Error trap for the function trap { Write-Error "An error occurred in New-Shell: $_" break } # Check for elevation if relevant $isElevated = $false trap { Write-Verbose "Could not determine elevation status: $_" $isElevated = $false continue } $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object System.Security.Principal.WindowsPrincipal($identity) $isElevated = $principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator) # Helper function to check executable function Test-Executable { param ([string]$Path) trap { Write-Verbose "Executable not found: $Path" return $false } if (Get-Command $Path -ErrorAction SilentlyContinue) { return $true } return $false } switch ($PSCmdlet.ParameterSetName) { 'User' { if ($isElevated) { Write-Warning "Current session is already elevated." } switch ($User) { 'PowerShell' { if (-not (Test-Executable 'PowerShell.exe')) { Write-Error "PowerShell.exe not found." return } trap { Write-Error "Failed to launch PowerShell: $_" break } Start-Process -FilePath "PowerShell.exe" -PassThru Write-Verbose "Launched PowerShell." } 'pwsh' { if (-not (Test-Executable 'pwsh.exe')) { Write-Error "pwsh.exe not found." return } trap { Write-Error "Failed to launch PowerShell Core: $_" break } Start-Process -FilePath "pwsh.exe" -PassThru Write-Verbose "Launched PowerShell Core." } default { Write-Error "Invalid value for -User parameter: $User" } } } 'RunAs' { if ($isElevated) { Write-Warning "Current session is already elevated." } switch ($RunAs) { 'PowerShellRunAs' { if (-not (Test-Executable 'PowerShell.exe')) { Write-Error "PowerShell.exe not found." return } trap { Write-Error "Failed to launch elevated PowerShell: $_" break } Start-Process -FilePath "PowerShell.exe" -Verb RunAs -PassThru Write-Verbose "Launched elevated PowerShell." } 'pwshRunAs' { if (-not (Test-Executable 'pwsh.exe')) { Write-Error "pwsh.exe not found." return } trap { Write-Error "Failed to launch elevated PowerShell Core: $_" break } Start-Process -FilePath "pwsh.exe" -Verb RunAs -PassThru Write-Verbose "Launched elevated PowerShell Core." } default { Write-Error "Invalid value for -RunAs parameter: $RunAs" } } } 'RunAsUser' { if (-not $PSBoundParameters.ContainsKey('Credentials') -or -not $Credentials) { Write-Error "-Credentials parameter is required for -RunAsUser." return } $shellExecutable = $null $shellDescription = $null switch ($RunAsUser) { 'PowerShellRunAsUser' { if (-not (Test-Executable 'PowerShell.exe')) { Write-Error "PowerShell.exe not found." return } $shellExecutable = 'PowerShell.exe' $shellDescription = 'Windows PowerShell' } 'pwshRunAsUser' { if (-not (Test-Executable 'pwsh.exe')) { Write-Error "pwsh.exe not found." return } $shellExecutable = 'pwsh.exe' $shellDescription = 'PowerShell Core' } default { Write-Error "Invalid value for -RunAsUser parameter: $RunAsUser" return } } $process = $null $useForceNewWindow = $PSBoundParameters.ContainsKey('ForceNewWindow') -and $ForceNewWindow.IsPresent trap { Write-Error "Failed to launch $shellDescription as specified user: $_" break } if ($useForceNewWindow) { if (-not (Test-Executable 'cmd.exe')) { Write-Error "cmd.exe not found. Unable to launch a new window." return } $titleValue = '""' if ($PSBoundParameters.ContainsKey('WindowTitle') -and -not [string]::IsNullOrWhiteSpace($WindowTitle)) { $sanitizedTitle = $WindowTitle.Replace('"', "'") $titleValue = '"' + $sanitizedTitle + '"' } $argumentList = New-Object -TypeName 'System.Collections.Generic.List[string]' [void]$argumentList.Add('/c') [void]$argumentList.Add('start') [void]$argumentList.Add($titleValue) [void]$argumentList.Add($shellExecutable) if ($PSBoundParameters.ContainsKey('ShellArgumentList') -and $ShellArgumentList) { foreach ($argument in $ShellArgumentList) { if ([string]::IsNullOrWhiteSpace($argument)) { continue } [void]$argumentList.Add($argument) } } $startProcessParameters = @{ FilePath = 'cmd.exe' ArgumentList = $argumentList.ToArray() Credential = $Credentials LoadUserProfile = $true UseNewEnvironment = $true PassThru = $true } $process = Start-Process @startProcessParameters Write-Verbose "Launched $shellDescription as specified user in a new console window." } else { $startProcessParameters = @{ FilePath = $shellExecutable Credential = $Credentials LoadUserProfile = $true UseNewEnvironment = $true PassThru = $true } if ($PSBoundParameters.ContainsKey('ShellArgumentList') -and $ShellArgumentList) { $startProcessParameters['ArgumentList'] = $ShellArgumentList } $process = Start-Process @startProcessParameters Write-Verbose "Launched $shellDescription as specified user." } if ($null -ne $process) { $process } } 'Terminal' { if (-not (Test-Executable 'wt.exe')) { Write-Error "wt.exe (Windows Terminal) not found." return } switch ($Terminal) { 'PowerShellTerminal' { trap { Write-Error "Failed to launch Windows PowerShell in Windows Terminal: $_" break } Start-Process -FilePath "wt.exe" -ArgumentList "new-tab -p 'Windows PowerShell'" -PassThru Write-Verbose "Launched Windows PowerShell in Windows Terminal." } 'pwshTerminal' { trap { Write-Error "Failed to launch PowerShell Core in Windows Terminal: $_" break } Start-Process -FilePath "wt.exe" -ArgumentList "new-tab -p 'PowerShell'" -PassThru Write-Verbose "Launched PowerShell Core in Windows Terminal." } default { Write-Error "Invalid value for -Terminal parameter: $Terminal" } } } 'TerminalRunAs' { if (-not (Test-Executable 'wt.exe')) { Write-Error "wt.exe (Windows Terminal) not found." return } switch ($TerminalRunAs) { 'PowerShellTerminalRunAs' { trap { Write-Error "Failed to launch elevated Windows PowerShell in Windows Terminal: $_" break } Start-Process -FilePath "wt.exe" -ArgumentList "new-tab -p 'Windows PowerShell'" -Verb RunAs -PassThru Write-Verbose "Launched elevated Windows PowerShell in Windows Terminal." } 'pwshTerminalRunAs' { trap { Write-Error "Failed to launch elevated PowerShell Core in Windows Terminal: $_" break } Start-Process -FilePath "wt.exe" -ArgumentList "new-tab -p 'PowerShell'" -Verb RunAs -PassThru Write-Verbose "Launched elevated PowerShell Core in Windows Terminal." } default { Write-Error "Invalid value for -TerminalRunAs parameter: $TerminalRunAs" } } } default { Write-Error "Unknown parameter set: $($PSCmdlet.ParameterSetName)" } } } end { Write-Verbose "New-Shell function execution completed." } } |