Quando um ou mais objetos se aproximam do host, o PowerShell examina o número de propriedades que o objeto possui.
Se o tipo de um objeto puder ser resolvido para um arquivo Format.ps1xml
correspondente (voltaremos a isso em um minuto), a convenção de formatação descrita nesse documento será usada - caso contrário, depende do número de propriedades um objeto tem.
Se um objeto tiver menos de 5 propriedades, o padrão será usar Format-Table
para formatação de saída:
PS C:\> New-Object psobject -Property ([ordered]@{PropA=1;PropB=2;PropC=3;PropD=4})
PropA PropB PropC PropD
----- ----- ----- -----
1 2 3 4
Se um objeto tiver mais propriedades, o padrão será Format-List
(que é o que você experimenta):
PS C:\> New-Object psobject -Property ([ordered]@{PropA=1;PropB=2;PropC=3;PropD=4;PropE=5})
PropA : 1
PropB : 2
PropC : 3
PropD : 4
PropE : 5
Agora, a razão pela qual os objetos retornados do cmdlet Get-Service
ou Get-Process
parecem ser formatados em uma tabela agradável, contextualmente relevante, com mais de 5 colunas, é que o PowerShell conseguiu encontrar um tipo documento de formatação específico para eles.
Esses arquivos de formatação estão todos localizados no diretório de instalação do PowerShell. Você pode localizar os arquivos padrão com:
Get-ChildItem $PSHome *.Format.ps1xml
Veja Get-Help about_Format.ps1xml
se você quiser criar seus próprios arquivos de formato.
A maneira como o PowerShell estabelece um link entre o tipo de um objeto e as exibições de formatação definidas é inspecionando a propriedade pstypenames
oculta:
PS C:\> $obj.pstypenames
System.Management.Automation.PSCustomObject
System.Object
O PowerShell simplesmente analisa essa lista ancestral de tipos para ver se ela tem uma visualização de formatação correspondente para o tipo.
Isso significa que você pode enganar o PowerShell na formatação de um objeto como se fosse de outro tipo, sem realmente se intrometer no sistema de tipo .NET subjacente.
Para mostrar isso, vamos criar um falso controlador de serviço - um objeto que se parece com algo que Get-Service
poderia ter retornado, mas na verdade não é:
PS C:\> $FauxService = New-Object psobject -Property @{
>>> "Name" = "FakeService3000"
>>> "Status" = "Faking"
>>> "DisplayName" = "TrustworthyService"
>>> "TrueName" = "Really a fake"
>>> "Author"="Clever Genius"
>>> }
PS C:\> $FauxService
Status : Faking
Name : FakeService3000
Author : Clever Genius
DisplayName : TrustworthyService
TrueName : Really a fake
Conforme descrito acima, o PowerShell mostra a saída de Format-List
, pois nosso psobject
tem 5 propriedades.
Agora, vamos tentar injetar um nome de tipo:
PS C:\> $FauxService.pstypenames.Insert(0,"System.ServiceProcess.ServiceController")
PS C:\> $FauxService
Status Name DisplayName
------ ---- -----------
Faking FakeService3000 TrustworthyService
Voila!