Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Resolving SIDs with WMI, WSMAN and PowerShell

Posted on October 15, 2013

In the world of Windows, an account SID can be a very enigmatic thing. Who is S-1-5-21-2250542124-3280448597-2353175939-1019? Fortunately, many applications, such as the event log viewer resolve the SID to an account name. The downside, is that when you are accessing that same type of information from PowerShell, you end up with the "raw' SID. And while there are a variety of command line tools, and probably even some cool .NET trick someone will share after I post this, you most likely want to find a PowerShell solution.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

Your initial assumption might be to use WMI. Searching Root\CIMv2 you'll even find a Win32_SID class. Woohoo! This is all I need to do:

get-wmiobject win32_sid -filter "sid='S-1-5-21-2250542124-3280448597-2353175939-1019'"

Well, no. As you can see in the figure, you can't query this particular class.

win32_sid-fail

Instead, you need to directly access the instance of the Win32_SID class. In PowerShell, the easy way is to use the [WMI] type accelerator, and specify the path to the instance.

[WMI]"root\cimv2:win32_sid.sid='S-1-5-21-2250542124-3280448597-2353175939-1019'"

wmi-sid

If you wanted to query the SID on a remote computer, the path would be \\SERVERNAME\root\cimv2:CLASSNAME.Keyproperty='Something'. But be aware that there is no way to specify alternate credentials using [WMI]. Although, you could query the Win32_Account class for the SID.

PS Scripts:\> get-wmiobject win32_account -filter "sid='S-1-5-21-2250542124-3280448597-2353175939-1019'"

AccountType : 512
Caption     : Serenity\localadmin
Domain      : Serenity
SID         : S-1-5-21-2250542124-3280448597-2353175939-1019
FullName    :
Name        : localadmin

This gives you the benefit of using a cmdlet, querying a remote computer and using alternate credentials.

In PowerShell 3.0 if you want to use the new CIM cmdlets and query WMI over WSMan, it is pretty easy to turn the previous command into a CIM command.

PS Scripts:\> get-ciminstance win32_account -filter "sid='S-1-5-21-2250542124-3280448597-2353175939-1019'"

Name             Caption              AccountType          SID                  Domain
----             -------              -----------          ---                  ------
localadmin       Serenity\localadmin  512                  S-1-5-21-22505421... Serenity

These queries are pretty good, but I believe that if you can go straight to the instance, so much the better. Unfortunately, I can't find any CIM related accelerator that would give me the same result as using the [WMI] accelerator. Remember, my goal is to leverage the new WSMan protocol. The solution is to use the Get-WSManInstance cmdlet.

Get-WSManInstance -ResourceURI "wmicimv2/Win32_SID" -SelectorSet @{SID="S-1-5-21-2250542124-3280448597-2353175939-1019"}

I think you can tell that the ResourceUri is the path to the class and the SelectorSet is a hashtable with key property, in this case SID, and the corresponding value. The result looks a little different, but the critical parts, like the account name are there.
get-wsmaninstance-1

Get-WSManInstance also supports alternate credentials. So given all of this, I put together a function called Resolve-SID that uses this approach. But as a fallback, you can also tell it to use WMI.

Function Resolve-SID {

<#
.Synopsis
Resolve account name from SID.
.Description
This command uses the WSMAN protocol to query WMI and resolve an account based
on its SID.  Using WMI it was possible to run a command like this:

[wmi]$user="\\SERVER01\root\cimv2:Win32_SID.Sid='S-1-5-18'"

But this relies on WMI and DCOM. This command uses a CIM-cmdlet approach that
queries WMI over the WSMAN protocol. If the SID can't be resolved to a user name
an exception will be thrown.

If you want to revert back to the WMI and DCOM approach, use the -UseWMI parameter.
However, you will not be able to use alternate credentials.

.Parameter SID
It is assumed the SID will start with S- and you must enter a complete SID.
Wildcards are not allowed.

.Parameter Computername
The name of the computer to query. The default is the localhost. The parameter
has an alias of CN.

.Parameter UseWMI
Revert to the legacy [WMI] command. This parameter has an alias of WMI.

.Parameter Credential
This parameter as an alias of RunAs. Specify either a username or a PSCredential
object.

.Notes
Last Updated: October 15, 2013
Version     : 1.0

Learn more:
 PowerShell in Depth: An Administrator's Guide (http://www.manning.com/jones2/)
 PowerShell Deep Dives (http://manning.com/hicks/)
 Learn PowerShell 3 in a Month of Lunches (http://manning.com/jones3/)
 Learn PowerShell Toolmaking in a Month of Lunches (http://manning.com/jones4/)
 PowerShell and WMI (http://www.manning.com/siddaway2/)

****************************************************************
* DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED *
* THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK.  IF   *
* YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, *
* DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING.             *
****************************************************************

.Example
PS C:\> resolve-sid S-1-5-18

Name                 : NT AUTHORITY\SYSTEM
AccountName          : SYSTEM
ReferencedDomainName : NT AUTHORITY
SID                  : S-1-5-18
Computername         : WIN8-LAP

.Example
PS C:\> resolve-sid S-1-5-21-1199145963-1667969739-787794555-1011 -Computername chi-win8-01 -Credential globomantics\administrator

Name                 : CHI-WIN8-01\localadmin
AccountName          : localadmin
ReferencedDomainName : CHI-WIN8-01
SID                  : S-1-5-21-1199145963-1667969739-787794555-1011
Computername         : CHI-WIN8-01

.Example
PS C:\> resolve-sid S-1-5-18 -verbose -computername jdhit-dc01 -UseWMI

VERBOSE: Starting Resolve-SID
VERBOSE: Resolving SID S-1-5-18 on jdhit-dc01
VERBOSE: Reverting back to WMI
VERBOSE: \\jdhit-dc01\root\cimv2:Win32_SID.SID='S-1-5-18'
VERBOSE: Associated account found

Name                 : NT AUTHORITY\SYSTEM
Accountname          : SYSTEM
ReferencedDomainName : NT AUTHORITY
SID                  : S-1-5-18
Computername         : JDHIT-DC01

VERBOSE: Ending Resolve-SID

.Link
Get-WSManInstance
Get-CIMInstance

.Link
https://jdhitsolutions.com/blog/2013/10/resolving-sids-with-wmi-wsman-and-powershell

.Inputs
Strings

.Outputs
A custom object
#>
[cmdletbinding(DefaultParameterSetName="CIM")]

Param(
[Parameter(Position=0,Mandatory=$True,HelpMessage="Enter a SID",
ValueFromPipeline,ValueFromPipelineByPropertyName)]
[ValidatePattern("^S-")]
[string]$SID,
[Parameter(ValueFromPipelineByPropertyName)]
[Alias("CN","PSComputername")]
[ValidateNotNullorEmpty()]
[string]$Computername=$env:computername,
[Alias("RunAs")]
[Parameter(ParameterSetName="CIM")]
[System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
[Parameter(ParameterSetName="WMI")]
[Alias("wmi")]
[switch]$UseWMI
)

Begin {
    Write-Verbose -Message "Starting $($MyInvocation.Mycommand)"  
} #begin
Process {
    Write-Verbose "Resolving SID $SID on $Computername"
    #build a hashtable of paramters to splat to Get-WSManInstance
    $paramHash=@{
        ErrorAction="Stop"
        ErrorVariable="MyError"
        ResourceURI="wmicimv2/win32_SID"
        SelectorSet=@{SID="$SID"}
        Computername=$Computername
    }

    If ($Credential.username) {
        Write-Verbose "Adding alternate credential for $($Credential.username)"
        $paramHash.Add("Credential",$Credential)
    }

    Try {

        #if UseWMI, use Get-WMIObject
        if ($UseWMI) {
            Write-Verbose "Reverting back to WMI"
            Write-Verbose "\\$computername\root\cimv2:Win32_SID.SID='$SID'"
            [WMI]$Result = "\\$computername\root\cimv2:Win32_SID.SID='$SID'"

        }
        else {
            $result = Get-WSManInstance @paramhash 
        }
    }
    Catch {
        Write-Warning "Get-WSManInstance failed to retrieve SID from $($Computername.ToUpper())"
        Write-Warning $myError.ErrorRecord
        #bail out
        Return
    }

    <#
    if there is no account name then the SID was not resolved, but there was
    no error. The query will still succeed and write an object to the pipeline
    but it won't have any useful information.  Only write the result to the pipeline
    if there is an associated account, otherwise an exception will be thrown.
    #>

    if ($result.AccountName) {
        Write-Verbose "Associated account found"
        $result | 
        Select @{Name="Name";Expression={"$($_.ReferencedDomainName)\$($_.AccountName)"}},
        Accountname,ReferencedDomainName,SID,
        @{Name="Computername";Expression={$Computername.ToUpper()}}
    }
    else {
        Write-Verbose "Failed to resolve SID. This is the result"
        Write-Verbose $($Result | Out-String)
        Throw "Failed to resolve SID $SID on $($Computername.ToUpper())"
    }
} #process

End {
    Write-Verbose -Message "Ending $($MyInvocation.Mycommand)"
} #end

} #close function Resolve-SID

I think between the comment based help, internal comments and verbose messages you should be able to understand how the function works. So now you have a variety of techniques for resolving SIDs. Querying locally, using [WMI] or querying the Win32_Account class for the SID should be sufficient performance-wise. But remotely, using [WMI] or Get-WSManInstance is significantly faster than querying and filtering. Using Get-WMIboject or Get-CIMInstance took between 600-750ms, where as the [WMI]approach took about 200MS and using Get-WSManInstance took 150MS.

I hope you are resolved to not let SIDS stand in your way any longer.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

9 thoughts on “Resolving SIDs with WMI, WSMAN and PowerShell”

  1. jvierra says:
    October 15, 2013 at 2:21 pm

    Jeff – Thanks. Very useful.

    1. Jeffery Hicks says:
      October 15, 2013 at 2:27 pm

      I’m sure there’s a very dev-centric solution to this but I try to stick to things an IT Pro would use or be able to figure out on their own.

      1. jvierra says:
        October 15, 2013 at 2:32 pm

        It does what it needs to do efficiently. No need for more.

        I spent some time looking at converting SIDS and didn’t think to try the [WMI] accelerator. I used the security classes. It was harder.

  2. Pasquale Lantella says:
    October 16, 2013 at 4:51 am

    Thank you very much there is now an additional way I could resolve SIDs.
    I used Dot.Net
    System.Security.Principal.SecurityIdentifier
    System.Security.Principal.NTAccount

    and I am asking if there is a way to use them remotly (except PSRemoting)?

    this is the function I used to resolve SIDs

    function Get-NamefromSID ($sid)
    {
    $objSID = New-Object System.Security.Principal.SecurityIdentifier($sid)
    try {
    $objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
    $objUser.Value
    } catch { $sid }
    }

    1. Jeffery Hicks says:
      October 16, 2013 at 8:51 am

      Thanks. I knew there was a .NET solution. Although this is limited to the local machine unless you use PowerShell remoting. I know even some IT Pros with .NET experience would opt for something like this. It works so you can’t really complain.

  3. Trevor Sullivan (@pcgeek86) says:
    October 16, 2013 at 10:29 am

    Good article, Jeff.

  4. Pingback: Microsoft Most Valuable Professional (MVP) – Best Posts of the Week around Windows Server, Exchange, SystemCenter and more – #51 - Flo's Datacenter Report
  5. Pingback: Microsoft Most Valuable Professional (MVP) – Best Posts of the Week around Windows Server, Exchange, SystemCenter and more – #51 - TechCenter - Blog - TechCenter - Dell Community
  6. Pingback: Dell’s Digest for October 21, 2013 | ServerKing

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d