Use the PowerShell [adsiSearcher] Type Accelerator to Search Active Directory

Hey, Scripting Guy! I am trying to get in touch with my inner programmer. The problem is that our company has cut head count in the past two years, and the remaining staff (myself included) is afraid to say no to anything, or to complain about too much work. The result has been many 12-hour days over the last two years. Training budget? Ha! That flew out the window months before the first pink slip arrived. So, I am struggling with attempting to learn a new skill, with no money for formal classes, or even to purchase a good book on the subject. While searching on the internet to learning about using Windows PowerShell to search Active Directory, I ran across your web site, but something confuses me. It seems that you use random methods to search AD, and I do not understand how you can use something in square brackets and it magically seems to work. How about starting from the beginning, I have been in IT for more than 30 years, so you can assume that I am mediocre, but trainable.

-- BB

Hello BB,

Microsoft Scripting Guy Ed Wilson here. Craig sent me a link to a really good deal on tea this afternoon. It seems that my favorite e-commerce web site was running a special on tea today. Far out; those kind of things seem like a ray of sunshine, on an otherwise cloudy day. I was in the middle of a cup of rather generic tea with some lotus blossoms, cinnamon, lemon grass, and a single pine needle (I like coming up with my own combinations of tea) with a plate of Tim Tams and raw walnuts. The Blues Brothers were wailing from my Zune HD, and I was experimenting with Windows PowerShell when the Communicator on my laptop went off. It was Craig and the aforementioned good deal on tea –yes, I was interested! It is really cool to have good friends that look out for your best interests.

BB, I will be your friend. I can’t believe I never really explained the adsisearcher square brackets (as opposed to sponges who wear square pants). Well, let’s dive in.

When using the [adsiSearcher] type accelerator, you can create an instance of the class by supplying the constructor to it directly on the same line. You do not use the New-Object cmdlet. For example, if you attempt to use the New-Object cmdlet to create an instance of the class, the error shown in the following image is displayed.

Typing [adsiSearcher] in the Windows PowerShell console, and pressing enter tells you the type accelerator is recognized, and that it will work, but it does not create an instance of the class – i.e., there is no constructor. Piping the type accelerator to the format-list cmdlet and asking for all the properties to be returned, supplies lots of cool information about the class, but does not return the information we saw when we used the new-object cmdlet to create the DirectorySearcher class. The details returned via the format-list cmdlet are seen here.

There is only one problem, and that is that no search filter has been supplied. This is a major source of confusion for people attempting to use the [adsisearcher] type accelerator; and it is especially true when people are used to the behavior of the new-object cmdlet / no constructor syntax that was examined earlier. Remember, that when one string value is supplied to the DirectorySearcher class for a constructor the value is interpreted as the filter. Therefore, [adsisearcher]”” specifies a filter that has no characters in it. The good thing is that the searchroot is automatically set to the root of the current domain. This is seen here.

With the new-object cmdlt and no constructor the “objectcategory=*” filter is created. But when [adsisearcher’”” is used, we have specifically created an instance of the DirectorySearcher class with no filter. There is no way, (that I know of. If you find a way, email me at scripter@microsoft.com) to create an instance of the DirectorySearcher class, using the [adsisearcher] type accelerator by supplying no constructor. With no filter, an error is returned when attempting to call the findone() method. This is seen here.

The problem is this is simply extra work. Because of this confusion, some bloggers have advocated simply not using the [adsisearcher] type accelerator, and always using New-Object to create the DirectorySearcher class. However, the goal is to do less work, not more, and in this case, the answer is easy. Supply the search filter when creating the class instance. The reason for creating an instance of the DirectorySearcher is that you are interested in searching for something; therefore, you will always have some sort of filter in mind.

If you want to use the default search filter that is created by the New-Object technique, use the “objectcategory=*” filter. This is seen here.

Because the DirectorySearcher object is created by using the [adsisearcher] type accelerator, and the filter is specified in the constructor, there is no need to store the intervening object in a variable. The intervening variable methodology is seen here.

The DirectorySearcher object is stored in the $a variable, and then the FindOne() method is called. To avoid the intervening variable, you can use a pair of parentheses to force evaluation of the first line of code. Once the DirectorySearcher object is created, the FindOne() method can be called. This is seen here.

The FindAll() method can also be called directly. This is shown in the following image.

BB, that is all there is to using the [adsisearcher] type accelerator. Searching Active Directory Domain Services week will continue tomorrow when we talk about searching AD DS for computers, and pinging them to see if they are up. We would love for you to follow us on Twitter or Facebook. If you have any questions, send email to us at scripter@microsoft.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

I can search for a group this way, very convenient. But what I struggle with thereafter is to get member property expanded (more than 2000 users). If I add a property PageSize=1000 to this adsisearcher, it will most likely work on finding the group (groups
more than 1500, suppose), but not the contents (member). How do I do that with adsisearcher?
What I have:
$root=([ADSI]"").distinguishedName #domain name
$searcher = [adsisearcher]"name=theGroupWithManyUsers" # Same as $searcher.Filter = "name=bob"
$n = $searcher.PropertiesToLoad.Add("cn"); # False variable, just to hide output?
$n = $searcher.PropertiesToLoad.Add("member");
$n = $searcher.PageSize = 1000
$a = $searcher.FindOne()
# $a.Properties.cn works, member does not work. Same with $a.Properties.Item("cn") and member instead.

This is a clean way to get information when you need to use a parameter value other than those allowed by the Ad module identity parameter. I created a script that compares information from one source to ad, using the ad module and a lot more get/set work
and it runs in 10 minutes. It does give me some strange anomolies part way through, though.

I decided to try this method since I could search on any value to find what I need. In this case I am using the employeeID value since it’s the only value that is consistent in the information I need to compare to AD.

I used your method above to create the script and it is running, but it has been running for over 5 hours, where my other script runs in 10 minutes.