Todo lo que querías saber sobre PSCustomObject

author
8 minutes, 26 seconds Read
  • 10/05/2020
  • 8 minutos para leer
    • j
    • m
    • s
    • j
    • c

PSCustomObjects son una gran herramienta para añadir a tu cinturón de herramientas de PowerShell. Vamos a empezar con los fundamentosy trabajar nuestro camino en las características más avanzadas. La idea de usar un PSCustomObject es tener una forma sencilla de crear datos estructurados. Echa un vistazo al primer ejemplo y tendrás una mejor idea de lo que significa.

Note

La versión original de este artículo apareció en el blog escrito por @KevinMarquette. El equipo dePowerShell agradece a Kevin por compartir este contenido con nosotros. Por favor, echa un vistazo a su blog enPowerShellExplained.com.

Crear un PSCustomObject

Me encanta usar en PowerShell. La creación de un objeto utilizable nunca ha sido más fácil.Debido a eso, voy a pasar por encima de todas las otras maneras que usted puede crear un objeto, pero necesito mencionar que la mayoría de estos ejemplos son PowerShell v3.0 y más reciente.

$myObject = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}

Este método funciona bien para mí porque yo uso hashtables para casi todo. Pero hay momentos en los que me gustaría que PowerShell tratara las hashtables más como un objeto. El primer lugar youounotice la diferencia es cuando se desea utilizar Format-Table o Export-CSV y te das cuenta de que ahashtable es sólo una colección de pares clave/valor.

A continuación, puede acceder y utilizar los valores como lo haría un objeto normal.

$myObject.Name

Convertir un hashtable

Ya que estoy en el tema, ¿sabías que puedes hacer esto:

$myHashtable = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}$myObject = $myHashtable

Yo prefiero crear el objeto desde el principio pero hay veces que tienes que trabajar con ahashtable primero. Este ejemplo funciona porque el constructor toma un hashtable para las propiedades del objeto. Una nota importante es que aunque este método funciona, no es un equivalente exacto. La mayor diferencia es que el orden de las propiedades no se conserva.

Enfoque de legado

Es posible que hayas visto a la gente usar New-Object para crear objetos personalizados.

$myHashtable = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}$myObject = New-Object -TypeName PSObject -Property $myHashtable

Esta forma es bastante más lenta, pero puede ser su mejor opción en las primeras versiones de PowerShell.

Guardar en un archivo

Encuentro la mejor manera de guardar un hashtable en un archivo es guardarlo como JSON. Usted puede importar de nuevo en un

$myObject | ConvertTo-Json -depth 1 | Set-Content -Path $Path$myObject = Get-Content -Path $Path | ConvertFrom-Json

Cubro más formas de guardar objetos a un archivo en mi artículo sobreLas muchas maneras de leer y escribir en archivos.

Trabajar con propiedades

Añadir propiedades

Todavía puedes añadir nuevas propiedades a tu PSCustomObject con Add-Member.

$myObject | Add-Member -MemberType NoteProperty -Name 'ID' -Value 'KevinMarquette'$myObject.ID

Quitar propiedades

También puedes eliminar propiedades de un objeto.

$myObject.psobject.properties.remove('ID')

La psobjectes una propiedad oculta que te da acceso a los metadatos del objeto base.

Enumerar nombres de propiedades

A veces necesitas una lista de todos los nombres de propiedades de un objeto.

$myObject | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name

También podemos obtener esta misma lista de la propiedad psobject.

$myobject.psobject.properties.name

Acceder dinámicamente a las propiedades

Ya he mencionado que se puede acceder directamente a los valores de las propiedades.

$myObject.Name

Puedes utilizar una cadena para el nombre de la propiedad y seguirá funcionando.

$myObject.'Name'

Podemos dar un paso más y utilizar una variable para el nombre de la propiedad.

$property = 'Name'$myObject.$property

Sé que parece extraño, pero funciona.

Convertir PSCustomObject en un hashtable

Para continuar con la última sección, puedes recorrer dinámicamente las propiedades y crear un hashtable a partir de ellas.

$hashtable = @{}foreach( $property in $myobject.psobject.properties.name ){ $hashtable = $myObject.$property}

Prueba de propiedades

Si necesitas saber si una propiedad existe, puedes simplemente comprobar que esa propiedad tiene un valor.

if( $null -ne $myObject.ID )

Pero si el valor pudiera ser $nullpuedes comprobar si existe verificando elpsobject.properties para ello.

if( $myobject.psobject.properties.match('ID').Count )

Añadir métodos de objetos

Si necesitas añadir un método de script a un objeto, puedes hacerlo con Add-Member y unScriptBlock. Tienes que usar la variable automática this de referencia al objeto actual. Aquí está ascriptblock para convertir un objeto en un hashtable. (mismo código del último ejemplo)

Entonces lo añadimos a nuestro objeto como una propiedad de script.

Entonces podemos llamar a nuestra función así:

$myObject.ToHashtable()

Objetos vs Tipos de valor

Los objetos y los tipos de valor no manejan las asignaciones de variables de la misma manera. Si se asignan tipos de valor entre sí, sólo el valor se copia a la nueva variable.

$first = 1$second = $first$second = 2

En este caso, $first es 1 y $second es 2.

Las variables de objeto mantienen una referencia al objeto real. Cuando se asigna un objeto a una newvariable, siguen haciendo referencia al mismo objeto.

$third = @{Key=3}$fourth = $third$fourth.Key = 4

Como $third y $fourth hacen referencia a la misma instancia de un objeto, tanto $third.key como$fourth.Key son 4.

psobject.copy()

Si necesitas una copia real de un objeto, puedes clonarlo.

$third = @{Key=3}$fourth = $third.psobject.copy()$fourth.Key = 4

Clone crea una copia superficial del objeto. Ahora tienen diferentes instancias y $third.key es 3y $fourth.Key es 4 en este ejemplo.

Llamo a esto una copia superficial porque si tienes objetos anidados. (donde las propiedades contienen otros objetos). Sólo se copian los valores de nivel superior. Los objetos hijos se referenciarán entre sí.

PSTypeName para tipos de objetos personalizados

Ahora que tenemos un objeto, hay algunas cosas más que podemos hacer con él que pueden no ser tan obvias. Lo primero que tenemos que hacer es darle un PSTypeName. Esta es la forma más común que veo la gente lo hace:

$myObject.PSObject.TypeNames.Insert(0,"My.Object")

Recientemente descubrí otra manera de hacer esto de este post por /u/markekraus. Hice un littledigging y más posts sobre la idea de Adam Bertram y Mike Shepard donde talkabout este enfoque que le permite definir en línea.

$myObject = @{ PSTypeName = 'My.Object' Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}

Me encanta lo bien que esto sólo encaja en el lenguaje. Ahora que tenemos un objeto con un nombre de tipo adecuado, podemos hacer algunas cosas más.

Nota

También puedes crear tipos personalizados de PowerShell usando clases de PowerShell. Para más información, veaPowerShell Class Overview.

Using DefaultPropertySet (the long way)

PowerShell decide por nosotros qué propiedades mostrar por defecto. Muchos de los comandos nativos tienen un archivo de formato.ps1xml que hace todo el trabajo pesado. Desde este post de Boe Prox, hay otra manera de hacer esto en nuestro objeto personalizado usando sólo PowerShell. Podemos darle unMemberSet para que utilice.

Ahora cuando mi objeto sólo cae en la cáscara, sólo mostrará esas propiedades por defecto.

Update-TypeData con DefaultPropertySet

Esto está bien pero recientemente vi una mejor manera cuando watchingPowerShell unplugged 2016 con Jeffrey Snover & Don Jones. Jeffrey estaba usandoUpdate-TypeData para especificar las propiedades por defecto.

$TypeData = @{ TypeName = 'My.Object' DefaultDisplayPropertySet = 'Name','Language'}Update-TypeData @TypeData

Eso es lo suficientemente simple que casi podría recordarlo si no tuviera este post como quickreference. Ahora puedo crear fácilmente objetos con un montón de propiedades y aún así darle una agradable cleanview cuando se mira desde el shell. Si necesito acceder o ver esas otras propiedades, que’restill allí.

$myObject | Format-List *

Update-TypeData con ScriptProperty

Algo más que saqué de ese video fue la creación de propiedades de script para sus objetos. Este sería un buen momento para señalar que esto funciona para los objetos existentes también.

Usted puede hacer esto antes de su objeto se crea o después y todavía va a funcionar. Esto es lo que hace que esto sea diferente a usar Add-Member con una propiedad de script. Cuando se utiliza Add-Member la forma Ireferenced antes, sólo existe en esa instancia específica del objeto. Este se aplica a todos los objetos con este TypeName.

Parámetros de función

Ahora puede utilizar estos tipos personalizados para los parámetros en sus funciones y scripts. Usted puede tener onefunction crear estos objetos personalizados y luego pasarlos en otras funciones.

param( $Data )

PowerShell requiere que el objeto es el tipo especificado. Lanza un error de validación si el tipo no coincide automáticamente para ahorrarte el paso de comprobarlo en tu código. Un gran ejemplo de dejar que PowerShell haga lo que mejor sabe hacer.

Función OutputType

También puede definir un OutputType para sus funciones avanzadas.

function Get-MyObject{ param ( ...

El valor del atributo OutputType es sólo una nota de documentación. No se deriva del código de la función ni se compara con la salida real de la función.

La razón principal por la que se utiliza un tipo de salida es para que la meta información sobre su función refleje sus intenciones. Cosas como Get-Command y Get-Help que su entorno de desarrollo puede aprovechar. Si quieres más información, entonces echa un vistazo a la ayuda para ello:about_Functions_OutputTypeAttribute.

Dicho esto, si estás usando Pester para probar tus funciones de forma unitaria, entonces sería una buena idea validar que los objetos de salida coincidan con tu OutputType. Esto podría atrapar las variables que acaban de caer en la tubería cuando no deberían.

Pensamientos finales

El contexto de esto fue todo acerca de , pero mucha de esta información se aplica toobjects en general.

He visto la mayoría de estas características de pasada antes, pero nunca los vio presentado como una colección deinformación en PSCustomObject. Justo esta semana pasada me topé con otra y me sorprendió que no la hubiera visto antes. Quería reunir todas estas ideas para que puedas ver el panorama general y ser consciente de ellas cuando tengas la oportunidad de utilizarlas. Espero que aprendas algo y encuentres la forma de incorporarlo a tus guiones.

Similar Posts

Deja una respuesta

Tu dirección de correo electrónico no será publicada.