Entendiendo la System.DirectoryServices.ResultPropertyCollection en PowerShell

Al trabajar con PowerShell y consultar Active Directory, es posible que te encuentres con un comportamiento desconcertante al intentar acceder a propiedades de la System.DirectoryServices.ResultPropertyCollection. En esta publicación, desentrañaremos un problema común que se encuentra al obtener información a través de un DirectorySearcher, específicamente, por qué dos salidas diferentes producen resultados inesperados. Vamos a explorar el problema, su raíz y cómo puedes resolverlo de manera efectiva.

El Problema

Has configurado un script de PowerShell que utiliza la clase DirectorySearcher para encontrar objetos de computadora en Active Directory, pero te enfrentas a discrepancias en tu salida. Aquí hay una replicación simplificada de tu código:

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

Cuando intentas imprimir los nombres de las computadoras, observas las siguientes dos salidas:

$computers | %{
    "Nombre del servidor entre comillas $_.properties.name" 
    "Nombre del servidor no entre comillas " + $_.properties.name 
}

Y luego:

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

El resultado muestra un nombre de tipo para la propiedad cuando está incluido entre comillas (System.DirectoryServices.SearchResult.properties.name) pero un valor cuando no lo está. Entender esta matiz es clave para dominar la recuperación de propiedades en PowerShell.

¿Por Qué Difieren las Salidas?

La discrepancia surge de cómo PowerShell evalúa variables y propiedades en cadenas. Cuando incluyes $_ en una cadena, PowerShell lo analiza como un objeto completo:

  • Contexto de Comillas: Al usar ";" en la cadena, como en "Nombre del servidor entre comillas $_.properties.name", PowerShell no evalúa la propiedad, sino que hace referencia al método ToString del objeto, que, en este caso, se default a el nombre de tipo de la propiedad.

  • Contexto Sin Comillas: Por el contrario, cuando lo usas sin comillas, como en "Nombre del servidor no entre comillas " + $_.properties.name, PowerShell evalúa primero la propiedad y luego la concatena a la cadena. Así, recupera el valor real almacenado en la propiedad en lugar del nombre de tipo.

Corrigiendo la Salida

Para recuperar el valor de la propiedad deseado mientras estás dentro de una cadena entre comillas, puedes invocar explícitamente la evaluación utilizando la sintaxis de subexpresión:

"Nombre del servidor entre comillas $($_.properties.name)"  

Este uso de $() le dice a PowerShell que evalúe lo que hay dentro antes de continuar con el resto de la cadena, dando como resultado la salida correcta que esperabas.

Explorando la Colección de Propiedades del Resultado

Recuerda, al trabajar con ResultPropertyCollection, estás tratando con una colección de propiedades. Siempre puedes explorar el modelo de objeto directamente desde la línea de comandos de PowerShell. Por ejemplo, canalizando $computers[0].properties a Get-Member revela información sobre los miembros y propiedades disponibles:

$computers[0].properties | Get-Member

Puedes ver la propiedad Values, que recupera un ICollection de los valores de la propiedad. Esta exploración mejora tu comprensión y te permite navegar a través de las propiedades de manera más efectiva.

Conclusión

Al trabajar con PowerShell y System.DirectoryServices de Active Directory, es crucial entender cómo la evaluación de cadenas actúa sobre objetos y sus propiedades. Al reconocer los diferentes contextos en los que se accede a estas propiedades, puedes evitar confusiones y recuperar la información que necesitas en el formato que esperas.

Navegar por construcciones complejas de PowerShell como ResultPropertyCollection puede parecer desalentador al principio, pero con práctica y una comprensión más profunda, descubrirás que se convierte en una segunda naturaleza en tu viaje de scripting.