Summary: Ed Wilson, Microsoft Scripting Guy, talks about launching an elevated Windows PowerShell shell.
Microsoft Scripting Guy, Ed Wilson, is here. Today I had a great talk with Steve, the Scripting Manager. One of the things we talked about was the importance of community, and how the Windows PowerShell community seems to be really engaged with the Windows PowerShell team and with other documentation efforts.
One of the great things that I love about the Windows PowerShell community is the interaction I have with them at user groups, conferences, and community events (such as the Atlanta TechStravaganza that is coming up). One of the questions that I get on a fairly regular basis has to do with working with Windows PowerShell as a non-elevated user.
Yesterday, I wrote a function that changes the title bar of my Windows PowerShell console based on whether the user is elevated (see Use Function to Determine Elevation of PowerShell Console).
The corollary to that is, "How do I elevate Windows PowerShell if I need to do so without having to create a second “admin” shortcut that automatically launches with Admin rights?" The following image shows the Advanced Properties window of the shortcut. Making an “admin” shortcut is as simple as checking Run as Administrator.
In the *nix world, such a function is known as sudo. So, I decided to call my function Start-ElevatedPowerShell and then I create an alias named sudo:
Function Start-ElevatedPowerShell
{
Start-Process PowerShell -Verb Runas
}
Set-Alias -Name sudo -Value Start-ElevatedPowerShell | out-null
After I save my function and alias to my Windows PowerShell profile, I close my Windows PowerShell shell, and then open it again. I then type sudoat the Windows PowerShell prompt, and the UAC prompt appears (strangely enough, it asks about allowing the program to make changes to my system. Hmmm, maybe it knows something I don’t know).
I say OK, and then my elevated Windows PowerShell prompt appears. This is shown here:
Cool, it works. Now my Windows PowerShell profile looks like this:
#------------------------------------------------------------------------------
#
# PowerShell console profile
# ed wilson, msft
#
# NOTES: contains five types of things: aliases, functions, psdrives,
# variables and commands.
# version 1.2
# 7/27/2015
# HSG 7-28-2015
#------------------------------------------------------------------------------
#Aliases
Set-Alias -Name ep -Value edit-profile | out-null
Set-Alias -Name tch -Value Test-ConsoleHost | out-null
Set-Alias -Name gfl -Value Get-ForwardLink | out-null
Set-Alias -Name gwp -Value Get-WebPage | out-null
Set-Alias -Name rifc -Value Replace-InvalidFileCharacters | out-null
Set-Alias -Name gev -Value Get-EnumValues | out-null
Set-Alias -Name sudo -Value Start-ElevatedPowerShell | out-null
#Variables
New-Variable -Name doc -Value "$home\documents" `
-Description "My documents library. Profile created" `
-Option ReadOnly -Scope "Global"
if(!(Test-Path variable:backupHome))
{
new-variable -name backupHome -value "$doc\WindowsPowerShell\profileBackup" `
-Description "Folder for profile backups. Profile created" `
-Option ReadOnly -Scope "Global"
}
#PS_Drives
New-PSDrive -Name Mod -Root ($env:PSModulePath -split ';')[0] `
-PSProvider FileSystem | out-null
#Functions
Function Edit-Profile
{ ISE $profile }
Function Test-ConsoleHost
{
if(($host.Name -match 'consolehost')) {$true}
Else {$false}
}
Function Replace-InvalidFileCharacters
{
Param ($stringIn,
$replacementChar)
# Replace-InvalidFileCharacters "my?string"
# Replace-InvalidFileCharacters (get-date).tostring()
$stringIN -replace "[$( [System.IO.Path]::GetInvalidFileNameChars() )]", $replacementChar
}
Function Get-TranscriptName
{
$date = Get-Date -format s
"{0}.{1}.{2}.txt" -f "PowerShell_Transcript", $env:COMPUTERNAME,
(rifc -stringIn $date.ToString() -replacementChar "-") }
Function Get-WebPage
{
Param($url)
# Get-WebPage -url (Get-CmdletFwLink get-process)
(New-Object -ComObject shell.application).open($url)
}
Function Get-ForwardLink
{
Param($cmdletName)
# Get-WebPage -url (Get-CmdletFwLink get-process)
(Get-Command $cmdletName).helpuri
}
Function BackUp-Profile
{
Param([string]$destination = $backupHome)
if(!(test-path $destination))
{New-Item -Path $destination -ItemType directory -force | out-null}
$date = Get-Date -Format s
$backupName = "{0}.{1}.{2}.{3}" -f $env:COMPUTERNAME, $env:USERNAME,
(rifc -stringIn $date.ToString() -replacementChar "-"),
(Split-Path -Path $PROFILE -Leaf)
copy-item -path $profile -destination "$destination\$backupName" -force
}
Function get-enumValues
{
# get-enumValues -enum "System.Diagnostics.Eventing.Reader.StandardEventLevel"
Param([string]$enum)
$enumValues = @{}
[enum]::getvalues([type]$enum) |
ForEach-Object {
$enumValues.add($_, $_.value__)
}
$enumValues
}
Function Test-IsAdmin
{
<#
.Synopsis
Tests if the user is an administrator
.Description
Returns true if a user is an administrator, false if the user is not an administrator
.Example
Test-IsAdmin
#>
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal $identity
$principal.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}
Function Start-ElevatedPowerShell
{
Start-Process PowerShell -Verb Runas
}
#Commands
Set-Location c:\
If(tch) {Start-Transcript -Path (Join-Path -Path `
$doc -ChildPath $(Get-TranscriptName))}
BackUp-Profile
if(Test-IsAdmin)
{ $host.UI.RawUI.WindowTitle = "Elevated PowerShell" }
else { $host.UI.RawUI.WindowTitle = "Mr $($env:USERNAME) Non-elevated Posh" }
That is all there is to using Windows PowerShell to start an elevated shell. Profile Week will continue tomorrow when I will talk about more cool stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy