July 29th, 2015

Use Function to Determine Elevation of PowerShell Console

Doctor Scripto
Scripter

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:

Image of console

This image shows the console when I right-click the Windows PowerShell icon and select Run as Administrator:

Image of console

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 

Author

The "Scripting Guys" is a historical title passed from scripter to scripter. The current revision has morphed into our good friend Doctor Scripto who has been with us since the very beginning.

0 comments

Discussion are closed.