Active Directory|PowerShell

Scaling the PowerShell Active Directory Searcher

Over the course of the last several articles, I have been demonstrating how to find Active Directory objects using the Active Directory Searcher Object from .NET and PowerShell. I have purposely kept my examples simple and constrained but today we are running free. I need to show you how to manage large environments.



Sponsored Content

What is “Inside Microsoft Teams”?

“Inside Microsoft Teams” is a webcast series, now in Season 4 for IT pros hosted by Microsoft Product Manager, Stephen Rose. Stephen & his guests comprised of customers, partners, and real-world experts share best practices of planning, deploying, adopting, managing, and securing Teams. You can watch any episode at your convenience, find resources, blogs, reviews of accessories certified for Teams, bonus clips, and information regarding upcoming live broadcasts. Our next episode, “Polaris Inc., and Microsoft Teams- Reinventing how we work and play” will be airing on Oct. 28th from 10-11am PST.

I know that my domain has 6351 user accounts. Let’s see what I get with the searcher object.

$searcher = New-Object system.DirectoryServices.DirectorySearcher
$searcher.filter = "(objectclass=user)"
$all = $searcher.FindAll()

Total users found (Image Credit: Jeff Hicks)
Total Users Found (Image Credit: Jeff Hicks)

Well, that cannot be right. Actually, it is. By default, the searcher object will only return the first 1000 matching objects. Heaven forbid that we ask a server to do any work! The solution is to modify the searcher’s PageSize property. The default value is 0. You can set it to a new value and PowerShell will return matching objects in pages or groups of that number.

$all = $searcher.FindAll()

I have experimented with different page sizes and cannot seem to find any value that is necessarily better than another. I tend to use 100 but you should experiment in your own test environment.

Regardless, $all now has 6447 objects! I have cleared the first hurdle and appear to be getting more than 1000 objects. However, I have even more than expected.

My searcher is defaulting to the domain root, so I know it is not missing anything. Using my Convert-ADSearchResult function from a previous article, I can group the results on the object type.

Grouping results by object type (Image Credit: Jeff Hicks)
Grouping Results by Object Type (Image Credit: Jeff Hicks)

This is interesting, especially for those of you who are not up to speed on LDAP schemas. When we refer to a user account, this is also a Person. Likewise, computer accounts can be counted as Users. The solution is to refine my search filter.

$searcher.filter = "(&(objectcategory=person)(objectclass=user))"
$all = $searcher.FindAll()

If you recall in a previous article, I showed you how to create a compound filter. Let’s check again.

Refined search results (Image Credit: Jeff Hicks)
Refined Search Results (Image Credit: Jeff Hicks)

If you are searching for users or other specifics in a large environment, you might need filters like this:

$searcher.filter = "(&(objectcategory=person)(objectclass=user)(name=mysampleuser3*))"

Limiting search (Image Credit: Jeff Hicks)
Limiting Search (Image Credit: Jeff Hicks)

Or keep extending your filter:

$searcher.filter = "(&(objectcategory=person)(objectclass=user)(name=a*)(title=tester))"

Using a compound search filter (Image Credit: Jeff Hicks)
Using a Compound Search Filter (Image Credit: Jeff Hicks)

That filter may look complicated. I will admit, they can be tricky to write. Let’s look at a trick.

Open Active Directory Users and Computers. Right-click on Saved Queries and select New – Query.

New AD Query (Image Credit: Jeff Hicks)
New Active Directory Query (Image Credit: Jeff Hicks)

If you plan on saving the query, you can enter a name. Otherwise, click the Define Query button. Use the dialogue box to configure whatever query you need.

Defining a custom query (Image Credit: Jeff Hicks)
Defining a Custom Query (Image Credit: Jeff Hicks)

I am going to build a query to find all disabled accounts. Click OK. You should now see the LDAP query string.

Getting the LDAP query string (Image Credit: Jeff Hicks)
Getting the LDAP Query String (Image Credit: Jeff Hicks)

You can select that text and copy it to Clipboard. Use that as your new search filter.

$searcher = New-Object system.DirectoryServices.DirectorySearcher
$searcher.filter = "(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=2))"
$searcher.PageSize = 100

There is no way I could have figured out that query on my own.

Showing disabled accounts (Image Credit: Jeff Hicks)
Showing Disabled Accounts (Image Credit: Jeff Hicks)

Now, I could pipe $disabled to Where-Object and filter out things like Guest. That would be easier than trying to modify the filter. A better choice would be to restrict my search scope.

Limiting the search (Image Credit: Jeff Hicks)
Limiting the Search (Image Credit: Jeff Hicks)

You could use the Saved Query wizard to get the filter syntax for your common search needs and create a set of PowerShell tools. In fact, I have given you a number of PowerShell functions that could serve as the starting point for your own toolbox. I might put together my own module when I have a little time. Although, I happened to check the PowerShell Gallery and found a very complete module called AdsiPS from fellow MVP Francois-Xavier Cat. He has assembled a complete toolkit that uses ADSI from the .NET Framework to manage Active Directory. This is very similar to what I have been demonstrating. None of it should require the RSAT Active Directory module. Run Install-Module AdsiPS to download and install it in your test network.

I hope you have found this series helpful. As always, comments welcome.

Related Topics:


Don't have a login but want to join the conversation? Sign up for a Petri Account

Comments (0)

Leave a Reply

External Sharing and Guest User Access in Microsoft 365 and Teams

This eBook will dive into policy considerations you need to make when creating and managing guest user access to your Teams network, as well as the different layers of guest access and the common challenges that accompany a more complicated Microsoft 365 infrastructure.

You will learn:

  • Who should be allowed to be invited as a guest?
  • What type of guests should be able to access files in SharePoint and OneDrive?
  • How should guests be offboarded?
  • How should you determine who has access to sensitive information in your environment?

Sponsored by:

Live Webinar: Active Directory Security: What Needs Immediate Priority!Live on Tuesday, October 12th at 1 PM ET

Attacks on Active Directory are at an all-time high. Companies that are not taking heed are being punished, both monetarily and with loss of production.

In this webinar, you will learn:

  • How to prioritize vulnerability management
  • What attackers are leveraging to breach organizations
  • Where Active Directory security needs immediate attention
  • Overall strategy to secure your environment and keep it secured

Sponsored by: