Impresión de propiedades de objeto en Powershell

120

Cuando trabajo en la consola interactiva si defino un nuevo objeto y le asigno algunos valores de propiedad como este:

$obj = New-Object System.String
$obj | Add-Member NoteProperty SomeProperty "Test"

Luego, cuando escribo el nombre de mi variable en la ventana interactiva, Powershell me da un resumen de las propiedades y valores del objeto:

PS C:\demo> $obj
SomeProperty                                                                                                                                                                                  
------------                                                                                                                                                                                  
Test

Básicamente, quiero hacer solo esto, pero desde una función en un script. La función crea un objeto y establece algunos valores de propiedad y quiero que imprima un resumen de los valores del objeto en la ventana de Powershell antes de regresar. Intenté usar Write-Host dentro de la función:

Write-Host $obj

Pero esto solo genera el tipo de objeto, no el resumen:

System.Object

¿Cómo puedo hacer que mi función genere un resumen de los valores de propiedad del objeto en la ventana de Powershell?

Juan
fuente

Respuestas:

187

Prueba esto:

Write-Host ($obj | Format-Table | Out-String)

o

Write-Host ($obj | Format-List | Out-String)
mjolinor
fuente
4
Tuve que pasar el -Forceparámetro para que funcione, por ejemploWrite-Host ($obj | Format-List -Force | Out-String)
Bart Verkoeijen
1
¡Uf! Todavía se muestra horizontalmente en la pantalla ... si alguna salida sale de su búfer, simplemente coloca .... Tengo un amor y odio con POSH
Kolob Canyon
Usando $objs = @();y $objs = $objs + $obj; puedo usar ConvertTo-Html: $ cols = $ objs | ConvertTo-Html -Fragment -Property Name, DataType, Default, Identity, InPrimaryKey, IsForeignKey, Description;
Kiquenet
33

Mi solución a este problema fue usar el bloque de subexpresión $ () .

Add-Type -Language CSharp @"
public class Thing{
    public string Name;
}
"@;

$x = New-Object Thing

$x.Name = "Bill"

Write-Output "My name is $($x.Name)"
Write-Output "This won't work right: $x.Name"

Da:

My name is Bill
This won't work right: Thing.Name
David Peters
fuente
16

Para imprimir las propiedades y los valores del objeto en Powershell. Los siguientes ejemplos funcionan bien para mí.

$ pool = Obtener el elemento "IIS: \ AppPools.NET v4.5"

$ piscina | Obtener miembro

   TypeName: Microsoft.IIs.PowerShell.Framework.ConfigurationElement#system.applicationHost/applicationPools#add

Name                        MemberType            Definition
----                        ----------            ----------
Recycle                     CodeMethod            void Recycle()
Start                       CodeMethod            void Start()
Stop                        CodeMethod            void Stop()
applicationPoolSid          CodeProperty          Microsoft.IIs.PowerShell.Framework.CodeProperty
state                       CodeProperty          Microsoft.IIs.PowerShell.Framework.CodeProperty
ClearLocalData              Method                void ClearLocalData()
Copy                        Method                void Copy(Microsoft.IIs.PowerShell.Framework.ConfigurationElement ...
Delete                      Method                void Delete()
...

$ piscina | Seleccionar-Objeto -Propiedad * # Puede omitir -Propiedad

name                        : .NET v4.5
queueLength                 : 1000
autoStart                   : True
enable32BitAppOnWin64       : False
managedRuntimeVersion       : v4.0
managedRuntimeLoader        : webengine4.dll
enableConfigurationOverride : True
managedPipelineMode         : Integrated
CLRConfigFile               :
passAnonymousToken          : True
startMode                   : OnDemand
state                       : Started
applicationPoolSid          : S-1-5-82-271721585-897601226-2024613209-625570482-296978595
processModel                : Microsoft.IIs.PowerShell.Framework.ConfigurationElement
...
ojos de gato
fuente
1
La última variante de esto funcionó mejor para mí, incluso puedo acortarlo a $x | select *, ideal para interactivos.
doblete el
No creo que esto funcione si quiero ponerlo en un guión. Si es así, creo que tienes que hacer algo adicional a lo que se indica para poder imprimirlo en la consola (es decir: Write-Output <something-something>)
Fractal
11

Consejo # 1

Nunca use Write-Host.

Consejo # 12

La forma correcta de generar información desde un cmdlet o función de PowerShell es crear un objeto que contenga sus datos y luego escribir ese objeto en la canalización mediante Write-Output.

-Don Jones: Maestro de PowerShell

Idealmente, su secuencia de comandos crearía sus objetos ( $obj = New-Object -TypeName psobject -Property @{'SomeProperty'='Test'}) y luego simplemente haría un archivo Write-Output $objects. Canalizaría la salida a Format-Table.

PS C:\> Run-MyScript.ps1 | Format-Table

Realmente deberían llamar a PowerShell PowerObjectandPipingShell.

MAL
fuente
4
Gracias Bob, he aceptado la respuesta de mjolinor ya que creo que responde a la pregunta de forma más directa, sin embargo, aprendí mucho de los enlaces que proporcionaste y estoy de acuerdo en que en la mayoría de los casos Write-Host no es adecuado. ¡Gracias!
John
1
La misma técnica funcionará, y probablemente sea más adecuada si se usa con Write-Verbose o Write-Debug.
mjolinor
4
Lo sé, llego muchos años tarde, pero no estoy de acuerdo con la Never use Write-Host.declaración. No puede usar Write-Output dentro de funciones que devuelven datos, porque "contaminarán" esta función. Ejemplo sencillo. ¿Adivina qué generará la función ReturnText? Es por eso que siempre uso las funciones internas Write-host. function ReturnText () {Write-Output "Algún mensaje aleatorio" return "Lo que quiero devolver"}
Denis Molodtsov
3
@DenisMolodtsov Estoy completamente de acuerdo. Con el propósito de registrar información, NUNCA debe usarse Write-Output a menos que la función sea trivial. Una vez que haya varios niveles de función y necesite devolver la salida, DEBE usar algo más, y Write-Host cumple con los requisitos.
RobG
2
Write-Host también se canalizará de inmediato desde una sesión remota, lo que le permitirá ver el progreso, y si una sesión remota arroja un error, se perderá la información de Write-Output.
RobG
3

Algunas notas generales.


$obj | Select-Object $obj | Select-Object -Property *

Este último mostrará todas las propiedades no intrínsecas y no generadas por el compilador. El primero no parece (siempre) mostrar todos los tipos de propiedad (en mis pruebas, parece mostrar la CodeProperty MemberTypecoherencia, aunque no hay garantías aquí).


Algunos cambios a tener en cuenta para Get-Member

  • Get-Memberno no conseguir que los miembros estáticos de forma predeterminada. Tampoco puede (directamente) llevarlos junto con los miembros no estáticos. Es decir, el uso del conmutador hace que solo se devuelvan miembros estáticos:

    PS Y:\Power> $obj | Get-Member -Static
    
       TypeName: System.IsFire.TurnUpProtocol
    
    Name        MemberType Definition
    ----        ---------- ----------
    Equals      Method     static bool Equals(System.Object objA, System.Object objB)
    ...
  • Utilice el -Force.

    El Get-Membercomando usa el parámetro Force para agregar los miembros intrínsecos y los miembros generados por el compilador de los objetos a la pantalla. Get-Memberobtiene estos miembros, pero los oculta de forma predeterminada.

    PS Y:\Power> $obj | Get-Member -Static
    
       TypeName: System.IsFire.TurnUpProtocol
    
    Name          MemberType     Definition
    ----          ----------     ----------
    ...
    pstypenames   CodeProperty   System.Collections.ObjectModel.Collection...
    psadapted     MemberSet      psadapted {AccessRightType, AccessRuleType,...
    ...

Úselo ConvertTo-Jsonpara una "serialización" legible y profunda

Yo no necesarias objetos recomiendan ahorrar utilizando JSON (uso Export-Clixmlen su lugar). Sin embargo, puede obtener una salida más o menos legible de ConvertTo-Json, que también le permite especificar la profundidad.

Tenga en cuenta que no especificar Depthimplica-Depth 2

PS Y:\Power> ConvertTo-Json $obj -Depth 1
{
    "AllowSystemOverload":  true,
    "AllowLifeToGetInTheWay":  false,
    "CantAnyMore": true,
    "LastResortOnly": true,
...

Y si no planea leerlo, puede -Compresshacerlo (es decir, quitar los espacios en blanco)

PS Y:\Power> ConvertTo-Json $obj -Depth 420 -Compress

Úselo -InputObjectsi puede (y está dispuesto)

El 99,9% de las veces cuando se usa PowerShell: o el rendimiento no importará o no le importa el rendimiento. Sin embargo , debe tenerse en cuenta que evitar la tubería cuando no la necesita puede ahorrar algunos gastos generales y agregar algo de velocidad (la tubería, en general, no es muy eficiente).

Es decir, si todo lo que tiene es un solo $objútil para imprimir (y no es tan vago como yo a veces para escribir -InputObject):

# select is aliased (hardcoded) to Select-Object
PS Y:\Power> select -Property * -InputObject $obj
# gm is aliased (hardcoded) to Get-Member
PS Y:\Power> gm -Force -InputObject $obj

Advertencia para Get-Member -InputObject: si $ obj es una colección (por ejemplo System.Object[]), terminará obteniendo información sobre el objeto de la colección en sí:

PS Y:\Power> gm -InputObject $obj,$obj2
   TypeName: System.Object[]

Name        MemberType            Definition
----        ----------            ----------
Count       AliasProperty         Count = Length
...

Si lo desea Get-Memberpara cada uno TypeNameen la colección (NB para cada uno TypeName, no para cada objeto, una colección de N objetos con todos los mismos TypeNamesolo imprimirá 1 tabla para eso TypeName, no N tablas para cada objeto) ... solo quédate con la tubería directamente.

YenForYang
fuente
1

Lo siguiente funcionó muy bien para mí. Parcheé todas las respuestas anteriores y leí sobre cómo mostrar las propiedades de los objetos en el siguiente enlace y obtuve la siguiente lectura breve sobre la impresión de objetos.

agregue el siguiente texto a un archivo llamado print_object.ps1:

$date = New-Object System.DateTime
Write-Output $date | Get-Member
Write-Output $date | Select-Object -Property *

Abra el símbolo del sistema de PowerShell, vaya al directorio donde existe ese archivo y escriba lo siguiente:

powershell -ExecutionPolicy ByPass -File is_port_in_use.ps1 -Elevated

Simplemente sustituya 'System.DateTime' con cualquier objeto que desee imprimir. Si el objeto es nulo, no se imprimirá nada.

Fractal
fuente
0
# Json to object
$obj = $obj | ConvertFrom-Json
Write-host $obj.PropertyName
Ramanujam Allam
fuente