, ,

Earlier today I was thinking about ways of testing if a script is running with admin rights.

Here’s the method I used to use in VBScript:

Set objWshNet = WScript.CreateObject("WScript.Network")
strComputer = LCase(objWshNet.ComputerName)

strTestUser = "TestIfAdmin"
Set objComputer = GetObject("WinNT://" & strComputer)
Set objTestUser = objComputer.Create("user", strTestUser)
objTestUser.SetPassword "P@ssw0rd"
If Err.Number = 0 Then
	objComputer.Delete "user", strTestUser
	rem Trap it here
End If

I don’t know what would have been considered a better solution, as that certainly felt a horrible method!

Anyway, for PowerShell I did some research and saw a number of techniques being used. This looks the best solution and is often quoted (returns True or False):

([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")

I don’t understand all that syntax (more on that later), so having looked in the .NET documentation I broke it down and commented it so it makes more sense and wrapped it in a function:

function Test-IfAdmin {
# Tests if the current Windows user is running as admin - ie UAC-aware.
    $currentWindowsIdentity = [Security.Principal.WindowsIdentity]::GetCurrent() # A static method.
    $currentWindowsPrincipal = New-Object -TypeName System.Security.Principal.WindowsPrincipal -ArgumentList $currentWindowsIdentity # Call a constructor.
    $adminRole = [Security.Principal.WindowsBuiltInRole]::Administrator # An Enum value.
    return $currentWindowsPrincipal.IsInRole($adminRole) # Returns a bool.

I’m a little undecided about which way of representing a value of an Enum seems more logical:



[Security.Principal.WindowsBuiltInRole] "Administrator"

The first makes me think “Static Method” and the second makes me think “Cast”. Neither sits quite so well with “Enum Value”!

I understand that the Constructor for a WindowsPrincipal takes a WindowsIdentity object as an argument. What I find confusing is that the following syntax (from the one liner earlier) appears to do just that:

[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()

Now to me that looks like a cast rather than calling a Constructor (and that’s confusing given that one class doesn’t appear to be derived from the other). I would be interested to hear the explanation of why this syntax works – it’s presumably calling the constructor.

BTW, I know you can use the following from PowerShell v3 onwards:

#requires -RunAsAdministrator