Summary: Ed Wilson, Microsoft Scripting Guy, talks about using a function to determine if a Windows PowerShell console is elevated.
Microsoft Scripting Guy, Ed Wilson, is here. I had a friend tell me that nearly half of all the cmdlets, functions, and whatever’s in Windows PowerShell 4.0 on Windows Server 2012 R2 required elevation to Admin rights. I can neither confirm nor deny this assertion, and I have not seen any official documentation about this. But I can tell you, that there are quite a few of these things that do require elevation. For example, the Hyper-V functions (even in Windows 8.1) require elevation. Even worse, when not elevated, you do not even get a report with an "access denied" type of error.
My friend's solution was simply to run Windows PowerShell elevated all the time, but my security background will not permit me to do that. I want to only use elevation when required. When I am done, I close out the elevated Windows PowerShell console, and go back to using my non-elevated Windows PowerShell console.
Although I normally run the Windows PowerShell console and the Windows PowerShell ISE with non-elevated rights, there are times when I need to know if I have elevated things. This is where my Test-IsAdmin function comes into play. I include this function in my Windows PowerShell Best Practices book, but it comes from a discussion on the internal Windows PowerShell alias at Microsoft from before Windows PowerShell was even called Windows PowerShell.
We were looking at various ways to determine if the current user has Admin rights, and this is the technique we pretty well settled on. I have written various versions of this, but I like this current version pretty well. Here is the function:
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)
}
The function returns a $true Boolean value if the user is in the role of administrator or $false if the user is not in the role of administrator. Luckily, when I elevate my Windows PowerShell console, I am in the role of administrator. When not elevated, I am not in that role. Cool how that works out.
So in my Windows PowerShell profile, I call the function, and then evaluate the results. I then change my Windows PowerShell title based on what the function call reports:
if(Test-IsAdmin)
{ $host.UI.RawUI.WindowTitle = "Elevated PowerShell" }
else { $host.UI.RawUI.WindowTitle = "Mr $($env:USERNAME) Non-elevated Posh" }
I place this code directly after I back up the Windows PowerShell profile. The resulting Windows PowerShell console is shown here when it is not elevated:
This image shows the console when I right-click the Windows PowerShell icon and select Run as Administrator:
Here is my complete Windows PowerShell profile:
#------------------------------------------------------------------------------
#
# 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
#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)
}
#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 a function to determine if the Windows PowerShell console is elevated. Join me 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