Imprimindo propriedades de objetos no Powershell


120

Ao trabalhar no console interativo, se eu definir um novo objeto e atribuir alguns valores de propriedade a ele, como este:

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

Então, quando eu digito o nome da minha variável na janela interativa, o Powershell me dá um resumo das propriedades e valores do objeto:

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

Basicamente, quero fazer exatamente isso, mas de dentro de uma função em um script. A função cria um objeto e define alguns valores de propriedade e eu quero imprimir um resumo dos valores do objeto na janela do Powershell antes de retornar. Tentei usar Write-Host na função:

Write-Host $obj

Mas isso apenas mostra o tipo de objeto, não o resumo:

System.Object

Como posso fazer com que minha função produza um resumo dos valores de propriedade do objeto na janela do Powershell?

Respostas:


187

Experimente isto:

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

ou

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

4
Tive que passar o -Forceparâmetro para fazer funcionar, por exemploWrite-Host ($obj | Format-List -Force | Out-String)
Bart Verkoeijen 01/09/2015

1
Ugh! Ele ainda é exibido horizontalmente na tela ... se alguma saída sair do seu buffer, ele simplesmente coloca .... Eu tenho um amor e ódio com POSH
Kolob Canyon

Usando $objs = @();e $objs = $objs + $obj; posso usar ConvertTo-Html: $ cols = $ objs | ConvertTo-Html -Fragment -Property Name, DataType, Default, Identity, InPrimaryKey, IsForeignKey, Description;
Kiquenet

33

Minha solução para esse problema foi usar o bloco de subexpressão $ () .

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"

Dá:

My name is Bill
This won't work right: Thing.Name

16

Para imprimir as propriedades e valores do objeto no Powershell. Os exemplos abaixo funcionam bem para mim.

$ pool = Get-Item "IIS: \ AppPools.NET v4.5"

$ pool | Get-Member

   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()
...

$ pool | Select-Object -Property * # Você pode omitir -Property

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
...

1
A última variante funcionou melhor para mim - pode até encurtá-la para $x | select *, ótimo para interativo.
dual em

Não acho que funcione se quiser colocar em um script. Em caso afirmativo, acho que você tem que fazer algo adicional do que o declarado para realmente imprimi-lo no console (ou seja: Write-Output <something-something>)
Fractal

11

Dica # 1

Nunca use Write-Host.

Dica # 12

A maneira correta de produzir informações de um cmdlet ou função do PowerShell é criar um objeto que contém seus dados e, em seguida, gravar esse objeto no pipeline usando Write-Output.

-Don Jones: PowerShell Master

Idealmente, seu script criaria seus objetos ( $obj = New-Object -TypeName psobject -Property @{'SomeProperty'='Test'}) e, em seguida, apenas faria a Write-Output $objects. Você canalizaria a saída para Format-Table.

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

Eles realmente devem chamar PowerShell PowerObjectandPipingShell.


4
Obrigado Bob, aceitei a resposta de mjolinor porque sinto que responde à pergunta mais diretamente, no entanto, aprendi muito com os links que você forneceu e concordo que na maioria dos casos Write-Host não é adequado. Obrigado!
John

1
A mesma técnica funcionará e provavelmente seria mais adequada se usada com Write-Verbose ou Write-Debug.
mjolinor,

4
Eu sei, estou muitos anos atrasado, mas discordo sobre a Never use Write-Host.afirmação. Você não pode usar Write-Output dentro de funções que retornam dados, porque isso "poluirá" esta função. Exemplo simples. Adivinha qual função ReturnText irá gerar? É por isso que eu sempre uso funções Write-host dentro. function ReturnText () {Write-Output "Alguma mensagem aleatória" return "O que eu quero retornar"}
Denis Molodtsov

3
@DenisMolodtsov Concordo plenamente. Para fins de registro de informações, a Gravação-Saída NUNCA deve ser usada, a menos que a Função seja trivial. Quando houver vários níveis de função e você precisar retornar a saída, DEVE usar outra coisa, e o Write-Host cumpre a conta.
RobG

2
O Write-Host também será imediatamente canalizado de volta de uma sessão remota, permitindo que você veja o progresso, e se uma sessão remota gerar um erro, as informações de Write-Output serão perdidas.
RobG

3

Algumas notas gerais.


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

O último mostrará todas as propriedades não intrínsecas e não geradas pelo compilador. O primeiro não parece (sempre) mostrar todos os tipos de propriedade (em meus testes, ele parece mostrar CodeProperty MemberTypeconsistentemente - sem garantias aqui).


Algumas opções a serem observadas para Get-Member

  • Get-Memberse não conseguir membros estáticos por padrão. Você também não pode obtê-los (diretamente) junto com os membros não estáticos. Ou seja, usar a opção faz com que apenas membros estáticos sejam retornados:

    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)
    ...
  • Use o -Force.

    O Get-Membercomando usa o parâmetro Force para adicionar à exibição os membros intrínsecos e os membros gerados pelo compilador dos objetos. Get-Memberobtém esses membros, mas os oculta por padrão.

    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,...
    ...

Use ConvertTo-Jsonpara profundidade e "serialização" legível

Eu não recomendo necessariamente salvar objetos usando JSON (use em Export-Clixmlvez disso). No entanto, você pode obter uma saída mais ou menos legível de ConvertTo-Json, o que também permite especificar a profundidade.

Observe que não especificar Depthimplica-Depth 2

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

E se você não planeja lê-lo, você pode -Compressfazê-lo (ou seja, tirar os espaços em branco)

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

Use -InputObjectse puder (e estiver disposto)

99,9% do tempo ao usar o PowerShell: ou o desempenho não importa ou você não se preocupa com o desempenho. Contudo , deve-se notar que evitar o cano quando você não precisa dele pode economizar alguma sobrecarga e adicionar alguma velocidade (a tubulação, em geral, não é supereficiente).

Ou seja, se tudo o que você tem é um único $objútil para imprimir (e não é tão preguiçoso como eu às vezes para digitar -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

Advertência para Get-Member -InputObject: Se $ obj for uma coleção (por exemplo System.Object[]), você acaba recebendo informações sobre o próprio objeto da coleção:

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

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

Se você quiser Get-Memberpara cada TypeNamena coleção (NB para cada TypeName, não para cada objeto - uma coleção de N objetos com todos iguais TypeNameimprimirá apenas 1 tabela para isso TypeName, não N tabelas para cada objeto) ...... apenas fique com a tubulação diretamente.


1

O abaixo funcionou muito bem para mim. Eu juntei todas as respostas acima e li sobre a exibição de propriedades de objetos no link a seguir e encontrei a breve leitura abaixo sobre como imprimir objetos

adicione o seguinte texto a um arquivo denominado print_object.ps1:

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

Abra o prompt de comando do PowerShell, vá para o diretório onde o arquivo existe e digite o seguinte:

powershell -ExecutionPolicy ByPass -File is_port_in_use.ps1 -Elevated

Basta substituir 'System.DateTime' por qualquer objeto que você deseja imprimir. Se o objeto for nulo, nada será impresso.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.