Understanding the System.DirectoryServices.ResultPropertyCollection
in PowerShell
When working with PowerShell and querying Active Directory, you may encounter some perplexing behavior when trying to access properties from the System.DirectoryServices.ResultPropertyCollection
. In this post, we will unravel a common issue encountered when fetching information through a DirectorySearcher
—specifically, why two different outputs yield unexpected results. Let’s explore the problem, its root, and how you can effectively resolve it.
The Problem
You’ve set up a PowerShell script that uses the DirectorySearcher
class to find computer objects in Active Directory, but you’re encountering discrepancies in your output. Here’s a simplified replication of your code:
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher.Filter = ("(objectclass=computer)")
$computers = $objSearcher.findall()
When you try to print the names of the computers, you observe the following two outputs:
$computers | %{
"Server name in quotes $_.properties.name"
"Server name not in quotes " + $_.properties.name
}
And then:
$computers[0] | %{"$_.properties.name"; $_.properties.name}
The result shows a type name for the property when included in quotes (System.DirectoryServices.SearchResult.properties.name
) but a value when not. Understanding this nuance is key to mastering property retrieval in PowerShell.
Why Do the Outputs Differ?
The discrepancy arises from how PowerShell evaluates variables and properties in strings. When you include $_
in a string, PowerShell looks at it as a whole object:
-
Quote Context: When using
";"
in the string, such as in"Server name in quotes $_.properties.name"
, PowerShell does not evaluate the property but references theToString
method of the object, which, in this case, defaults to the type name of the property. -
Non-Quote Context: Conversely, when you use it without quotes, like in
"Server name not in quotes " + $_.properties.name
, PowerShell evaluates the property first and then concatenates it to the string. Thus, it retrieves the actual value stored in the property rather than the type name.
Correcting the Output
To retrieve the intended property value while inside a quoted string, you can explicitly invoke evaluation using subexpression syntax:
"Server name in quotes $($_.properties.name)"
This use of $()
tells PowerShell to evaluate what’s inside before proceeding with the rest of the string, yielding the correct output you expected.
Exploring Result Property Collection
Remember, when working with ResultPropertyCollection
, you are dealing with a collection of properties. You can always explore the object model directly from the PowerShell command line. For instance, piping $computers[0].properties
to Get-Member
reveals information about available members and properties:
$computers[0].properties | Get-Member
You can see the Values
property, which retrieves an ICollection
of the property’s values. This exploration enhances your understanding and allows you to navigate through properties more effectively.
Conclusion
When working with PowerShell and Active Directory’s System.DirectoryServices
, it’s crucial to grasp how string evaluation acts upon objects and their properties. By recognizing the different contexts in which these properties are accessed, you can avoid confusion and retrieve the information you need in the format you expect.
Navigating complex PowerShell constructs like ResultPropertyCollection
may seem daunting at first, but with practice and deeper understanding, you will find it becomes second nature in your scripting journey.