Skip to content

Instantly share code, notes, and snippets.

@jborean93
Created May 22, 2020 21:25
Show Gist options
  • Select an option

  • Save jborean93/be94d9255e601e6ddfeddb752fa486b5 to your computer and use it in GitHub Desktop.

Select an option

Save jborean93/be94d9255e601e6ddfeddb752fa486b5 to your computer and use it in GitHub Desktop.
Starts Windows Terminal as the current user, another user, and optionally elevated.
# Copyright: (c) 2020, Jordan Borean (@jborean93) <[email protected]>
# MIT License (see LICENSE or https://opensource.org/licenses/MIT)
Function Start-WindowsTerminal {
<#
.SYNOPSIS
Start Windows Terminal from PowerShell.
.DESCRIPTION
Start Windows Terminal from PowerShell. This can be done as the current user, another user, and optionally
elevated through UAC.
.PARAMETER Credential
Custom user credential to use when starting windows terminal. Unless UAC is disabled or not applied to the target
account, the process will be a limited process. Use with -Elevated to elevate the process.
.PARAMETER Elevated
Whether to run as an elevated user or not. This will also result in a interactive UAC prompt. Can be combined with
-Credential to start Windows Terminal elevated as another user when the current user is also an admin.
.NOTES
To start WindowsTerminal as another user, the WindowsTerminal app must be installed on that user's profile. If it
is not then this cmdlet will fail with wt.exe not found.
#>
[CmdletBinding()]
param (
[PSCredential]
$Credential,
[Switch]
$Elevated
)
$splitUser = {
param ([PSCredential]$Credential)
# ProcessStartInfo requires a NETLOGON username form 'DOMAIN\user' to be split up into different values. This
# extracts the domain part if that user is in that form otherwise keeps it as is.
$username = $Credential.UserName
$domain = [NullString]::Value
if ($username.Contains('\')) {
$domain, $username = $username.Split('\\', 2)
}
$domain, $username
}
if ($Credential -and $Elevated) {
# This is a tricky process, we cannot elevate and run as another user at the same time so we need to do it
# step by step. These steps are:
#
# 1. Start a process as another user
# 2. Create an elevated process for that user using UAC
# 3. Start wt.exe from that elevated process
#
# We can also only start wt.exe from that elevated process, we cannot start it as elevated from the get go.
# See 'elseif ($Elevated)' for more details.
$elevation = {
Start-Process -FilePath powershell.exe -ArgumentList 'wt.exe' -WindowStyle Hidden -Verb Runas
}
$elevationCommand = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($elevation.ToString()))
# Start powershell as another user which will elevate itself through UAC then call wt.exe.
$domain, $username = &$splitUser -Credential $Credential
$psi = [System.Diagnostics.ProcessStartInfo]@{
FileName = 'powershell.exe'
Arguments = "-WindowStyle Hidden -EncodedCommand $elevationCommand"
LoadUserProfile = $true
UserName = $username
Domain = $domain
Password = $Credential.Password
UseShellExecute = $false
WindowStyle = 'Hidden'
}
$null = [System.Diagnostics.Process]::Start($psi)
}
elseif ($Credential) {
# Using 'Start-Process -Credential $Credential' will spawn the process as the other user but the window
# doesn't allow any interaction. .NET has no limitations here so we use that instead.
$domain, $username = &$splitUser -Credential $Credential
$psi = [System.Diagnostics.ProcessStartInfo]@{
FileName = 'wt.exe'
LoadUserProfile = $true
UserName = $username
Domain = $domain
Password = $Credential.Password
UseShellExecute = $false
WindowStyle = 'Hidden'
}
$null = [System.Diagnostics.Process]::Start($psi)
}
elseif ($Elevated) {
# Want to start it elevated through UAC. Unfortunately we cannot just call wt.exe through UAC as that won't
# place the proper groups to the new token that are needed to access wt.exe. By starting a new powershell
# that is elevated then wt.exe, it will inherit the elevated access token and have the proper token
# capabilities applied.
Start-Process -FilePath powershell.exe -ArgumentList 'wt.exe' -WindowStyle Hidden -Verb Runas
}
else {
# Just want to start a new instance, call normally.
Start-Process -FilePath wt.exe
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment