The Ins and Outs of Using DSQuery with Windows PowerShell

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using DSQuery to return results for use in Windows PowerShell.

Hey, Scripting Guy! I like using the DSQuery tool to search Active Directory Domain Services (AD DS). Can I use that tool with Windows PowerShell?

—WS

Hello WS,

Microsoft Scripting Guy, Ed Wilson, is here. Yes, it is possible, but I think that there are problems with using the DSQuery tool from within Windows PowerShell. The problems come from the nature of the DSQuery tool itself, and not from within Windows PowerShell. If you are good at using DSQuery and DSGet, you might not have any problems, but personally, I think there are easier methods. I wrote a Hey, Scripting Guy! Blog called Query Active Directory Without Writing a Script; and in that blog, I discuss different methods of querying AD DS. You can refer to that blog for additional information about the tools.

The bad thing about DSQuery

The bad thing about it is not so much a limitation of DSQuery, as it is a limitation of all such command-line utilities. It returns strings; therefore, if the output is not exactly to my liking, I have to do string manipulation—and personally, I hate string manipulation. I have always hated string manipulation—from the VBScript days, and even back into the days of CPM. String manipulation simply is not “my thing.”

Another bad thing about DSQuery is that it is not installed by default, and the only way to get it on my laptop running Windows 8 is to download and to install the Remote Server Administration Tools (RSAT), which is yet to be released. A bad thing about the RSAT is that it is version specific, and even service pack specific. In Windows 7, I had to uninstall the RSAT, install Service Pack 1, then reinstall the RSAT. Of course, I did not find that out until after the service pack installation failed. So, I am always a little leery of installing extra stuff that I really do not need on my computers.

Of course, by using Windows PowerShell remoting, I do not need to install the RSAT on my computer only to use DSQuery. I can easily use the Invoke-Command cmdlet to perform the remote query on a server (by default all domain controllers will have DSQuery installed with their admin tools). I first store the credentials that I need in a variable I call $cred. I use the Get-Credential cmdlet to obtain the credential object. Next, I use the Invoke-Command cmdlet to specify the remote server from which to process the query, and I pass the credentials. I store the returned array of strings in the $computers variable, and I then display the strings. The commands are shown here.

$cred = get-credential iammred\administrator

$computers = invoke-command -cn dc3 {dsquery computer} -cred $cred

$computers

The commands and the associated output are shown in the image that follows.

The strings are included in the output. To obtain only the computer name itself requires further processing. One way to get the computer name would be to use a regular expression and pick out the stuff following the first CN= that occurs before a comma. That would work, but I like regular expressions even less than I like string manipulation.

Therefore, I can turn the returned strings into ADSPath and supply that to the [adsi] type accelerator. To do that is not to horribly complicated. First, I need to get the output into a fashion I can pass to the [adsi] type accelerator. This is a two-step operation. First I replace the first CN=with LDAP://CN= and store the results back into a variable. This command is shown here.

$ads = $computers -replace '^"CN=', '"LDAP://CN='

For some reason, it does not seem to like the quotation marks when I pass it to [adsi], so I need to remove them. Here is the command that I use for that.

$ads = $ads | % {$_ -replace '"', ""}

Now, I can use ADSPath to create a DirectoryEntry object and retrieve the CN property (the basic computer name). This command is shown here.

$ads | Foreach-Object {([adsi]$_).cn}

The nice thing about objects

The nice thing about objects is that they make it easy to access different parts of information. For example, when I use the [adsisearcher] type accelerator to find computers from inside AD DS, it returns a SearchResult object. This object contains a number of methods, but it also contains two properties. The first property is the Pathproperty, which is a string. The second property, the Propertiesproperty contains an additional object. The output from the Get-Member cmdlet displays this information.

To obtain only the computer names in Windows PowerShell 2.0, I can use the GetEnumeratormethod and then select only the CNproperty. In addition, I can create a custom object that contains only the properties I want. First, here is the code to select only the computer names.