Quick Active Directory search with “pure” PowerShell

find-personAs much as I like tools designed for work AD – both from Microsoft and Quest – I’m sometimes amazed how quicker pure ADSI/ ADSISearcher calls can be. Today I said to myself: enough. I know LDAP Filters/ ActiveDirectory attributes good enough to write simple function for myself that would give me all advantages cmdlets give of former, and lightning speed of latter.

Also: I know, I can use LDAPFilters in either tools, but I do not like that I have to pass full filter, I wanted something interactive-work friendly. Normally you have to move back and forth (unless you always start with “(&())”) and always remember to quote everything (or escape brackets).

Another thing – I wanted something that would give me properties I care about rather than one that someone else considers important. Namely, my target was:

Search-AD name=Biel*, givenname=Bart* name, division, otherTelephone

As you can see – I wanted specify only “meat” of LDAPFilter – assumption was I want to combine filters rather that have either condition met. Also, I wanted to be able to specify list of properties next. I wanted to have option to specify SearchRoot, if I would ever need it (e.g. searching different domain). And – to be honest – it was relatively easy to implement. I did not care about error handling – assumption is that this function will be used interactively rather than in scripts, so I can “handle” errors when I get them. Uśmiech Final code:

function Search-AD {            
param (            
    [string[]]$Filter,            
    [string[]]$Properties,            
    [string]$SearchRoot            
)            
            
    if ($SearchRoot) {            
        $Root = [ADSI]$SearchRoot            
    } else {            
        $Root = [ADSI]''            
    }            
            
    if ($Filter) {            
        $LDAP = "(&({0}))" -f ($Filter -join ')(')            
    } else {            
        $LDAP = "(name=*)"            
    }            
            
    if (!$Properties) {            
        $Properties = 'Name','ADSPath'            
    }            
            
    (New-Object ADSISearcher -ArgumentList @(            
        $Root,            
        $LDAP,            
        $Properties            
    ) -Property @{            
        PageSize = 1000            
    }).FindAll() | ForEach-Object {            
        $ObjectProps = @{}            
        $_.Properties.GetEnumerator() |             
            Foreach-Object {            
                $ObjectProps.Add(            
                    $_.Name,             
                    (-join $_.Value)            
                )            
        }            
        New-Object PSObject -Property $ObjectProps |             
            select $Properties            
    }            
}            

And that’s it: I get information relatively quick, and can use this command for any query:

Search-AD -Filter name=WAR000269 | foreach {             
    Search-AD objectClass=msFVE-RecoveryInformation msFVE-RecoveryPassword $_.adspath            
}            

… and get BitLocker recovery key stored in AD for any computer in domain (that I have necessary access to) within milliseconds. In case you wonder: yes, I do know both msFVE elements by hard. Puszczam oczko

Advertisements

5 thoughts on “Quick Active Directory search with “pure” PowerShell

  1. Hello I am wonder if there is a way to add in ADSI alternate credentials to make this script work. I have been trying for the last week and a half and have ADSI with alternate credentials working but can’t get them to work with this script. Any help would be greatly appreciated.

    • In such a case you have to use proper constructor for $Root.
      Let say you add parameter $Credential:

      param (
      # ... other parameters
      [System.Management.Automation.PSCredential]$Credential
      )

      Once you do that, you can use it to create proper $Root object that will connect using alternate credentials:

      if ($Credential) {
      $PlainText = $Credential.GetNetworkCredential()
      $UserName = '{0}\{1}' -f $PlainText.Domain, $PlainText.UserName
      $Root = New-Object ADSI -ArgumentList $SearchRoot, $UserName, $PlainText.Password
      }

      Once it’s done – you can specify alternate credentials and get same results.

  2. Pingback: Wspieramy stronicowanie | PowerShell po polsku

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s