views:

680

answers:

3

I'm missing something here:

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher  
$objSearcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry  
$objSearcher.Filter = ("(objectclass=computer)")  
$computers = $objSearcher.findall()

So the question is why do the two following outputs differ?

$computers | %{ 
"Server name in quotes $_.properties.name" 
"Server name not in quotes " + $_.properties.name 
}
PS> $computers[0] | %{"$_.properties.name"; $_.properties.name}
System.DirectoryServices.SearchResult.properties.name
GORILLA
A: 

I believe it has to do with the way that PS interpolates information in the "". Try this:

"Server name in quotes $($_.properties).name"

Or you may even need one more set of $(). I'm not somewhere that I can test it at right now.

EBGreen
A: 

Close-- The below works correctly, but I'd be interested if anyone has a deeper explanation.

PS C:\> $computers[0] | %{ "$_.properties.name"; "$($_.properties.name)" }
System.DirectoryServices.SearchResult.properties.name
GORILLA

So it would seem that $_.properties.name doesn't deference like I expected it to. If I'm visualizing properly, the fact that the name property is multivalued causes it to return an array. Which (I think) would explain why the following works:

$computers[0] | %{ $_.properties.name[0]}

If "name" were a string this should return the first character, but because it's an array it returns the first string.

slipsec
+1  A: 

When you included $.properties.name in the string, it was returning the type name of the property. When a variable is included in a string and the string is evaluated, it calls the ToString method on that object referenced by the variable (not including the members specified after). In this case, the ToString method is returning the type name. You can force the evaluation of the variable and members similar to what EBGreen suggested, but by using "Server name in quotes $($.properties.name)" In the other scenario PowerShell is evaluating the variable and members specified first and then adding it to the previous string.

You are right that you are getting back a collection of properties. If you pipe $computer[0].properties to get-member, you can explore the object model right from the command line.
The important part is below.

TypeName: System.DirectoryServices.ResultPropertyCollection

Name MemberType Definition


Values Property System.Collections.ICollection Values {get;}

Steven Murawski