De Volta às Origens: Compreendendo Objetos do PowerShell

O PowerShell é uma linguagem poderosa. Mas o que torna essa linguagem de script tão poderosa? Objetos do PowerShell. O que são esses objetos mágicos e como o PowerShell trabalha com eles? Fique ligado para descobrir.

O PowerShell é uma linguagem orientada a objetos e um shell. Isso é uma mudança em relação aos shells tradicionais como cmd e Bash. Esses shells tradicionais focavam em texto, também conhecido como strings, e embora ainda sejam úteis, são limitados em suas capacidades. Quase tudo no PowerShell é um objeto.

Neste artigo, você aprenderá alguns conceitos-chave quando se trata de objetos no PowerShell. Ao final deste artigo, você terá aprendido como aplicar esse conhecimento em seus próprios scripts através de exemplos de código úteis e visualizações.

Se você é mais um aprendiz visual, sinta-se à vontade para assistir ao vídeo complementar deste artigo abaixo.

Então prepare-se! Você está prestes a ter uma experiência memorável que o ajudará a dominar o conceito de objetos no PowerShell!

Pré-requisitos

Neste artigo, você vai aprender sobre objetos no PowerShell através de uma abordagem prática. Se você optar por seguir e experimentar os exemplos de código, o Windows PowerShell 5.1 ou qualquer versão do PowerShell 6+ deve funcionar. No entanto, todos os exemplos que você verá serão realizados no Windows 10 build 1903 com Windows PowerShell 5.1.

Entendendo a Anatomia de um Objeto

Os objetos estão em toda parte no PowerShell. Você pode estar se perguntando “Como é um objeto?” Nesta primeira seção, você terá uma visão geral do que consiste um objeto. Depois de ter uma visão ampla do que faz um objeto ser um objeto, você poderá mergulhar em alguns exemplos de código!

Descobrindo Membros de Objetos com Get-Member

Os objetos têm muitos diferentes tipos de informações associadas a eles. No PowerShell, essa informação às vezes é chamada de membros. Um membro de objeto é um termo genérico que se refere a todas as informações associadas a um objeto.

Para descobrir informações sobre um objeto (membros), você pode usar o cmdlet Get-Member. O cmdlet Get-Member é um comando útil que permite encontrar propriedades disponíveis, métodos e assim por diante para qualquer objeto no PowerShell.

Por exemplo, vamos dizer que você quer ver os membros para um objeto específico retornado através do cmdlet Get-Service. Você pode fazer isso encaminhando a saída do comando Get-Service para o cmdlet Get-Member como visto abaixo.

language-powershell
Get-Service -ServiceName 'BITS' | Get-Member

Acostume-se com o cmdlet Get-Member. Você vai usá-lo muito neste artigo.

Todo comando no PowerShell que produz saída pode ser encaminhado para o Get-Member. Apenas lembre-se de fazer deste cmdlet o último na pipeline, pois ele sobrescreverá a saída com a sua própria saída.

Tipos de Objetos e Classes

Sem entrar em muitos detalhes sobre programação orientada a objetos, cada objeto possui um “esquema”. O “esquema” de um objeto é uma espécie de modelo que contém a planta baixa para criar um objeto. Essa planta baixa é chamada de tipo.

Cada objeto no PowerShell tem um tipo específico. Cada objeto possui uma planta baixa a partir da qual foi criado. O tipo de objeto é definido por uma classe. Considere este exemplo; 9 é número, Bluegill é peixe, Labrador é cão, etc. A classe vem antes do tipo.

Objetos são instâncias de classes com um tipo específico.

Não se preocupe em aprofundar muito nesse tópico. A menos que você seja um desenvolvedor de software, provavelmente não precisa se preocupar muito com a semântica neste momento. No entanto, é um conceito importante de conhecer em um nível básico.

Propriedades

O conceito mais importante sobre objetos que você deve entender são as propriedades. Propriedades são atributos que descrevem um objeto. Um objeto pode ter muitas propriedades diferentes representando vários atributos.

Uma das maneiras mais fáceis de descobrir quais propriedades existem em objetos é usando o cmdlet Get-Member. Você pode ver abaixo que, usando o parâmetro MemberType, o Get-Member limitará a saída retornada apenas para objetos. Você também verá que ele exibe o tipo de objeto System.ServiceProcess.ServiceController.

PS51> Get-Service | Get-Member -MemberType Property
Get-Service object properties

Agora, tome o exemplo do serviço BITS abordado anteriormente e veja os valores específicos das propriedades desse objeto usando o código abaixo. O cmdlet Get-Member permite que você encontre os nomes das propriedades, mas não os valores. No entanto, usando o cmdlet Select-Object do PowerShell, você pode inspecionar os valores das propriedades.

Abaixo, você pode ver que StartType é uma propriedade no objeto. O objeto retornado tem muitos membros diferentes, mas ao usar o cmdlet Select-Object, está limitando a saída para apenas mostrar essa propriedade.

PS51> Get-Service -ServiceName 'BITS' | Select-Object -Property 'StartType'
BITS service start type

As propriedades são, de longe, o componente mais comum de um objeto com o qual você trabalhará no PowerShell.

Aliases

Algumas propriedades têm um MemberType de Alias. Os aliases são pseudônimos para nomes de propriedades. Às vezes, podem dar nomes mais intuitivos às propriedades.

Você pode ver um exemplo de um objeto com aliases usando novamente o cmdlet Get-Service, como mostrado abaixo. A propriedade Name é um alias para ServiceName e RequiredServices é um alias para a propriedade ServicesDependedOn.

PS51> Get-Service | Get-Member -MemberType 'AliasProperty'
AliasProperty members on service objects

Quando uma propriedade tem um alias, você pode referenciar o valor dessa propriedade usando o nome do alias em vez do nome real da propriedade. Neste exemplo, um atributo descritivo como Name e RequiredServices é mais intuitivo e mais fácil de digitar do que ServiceName e ServicesDependedOn.

Você pode ver um exemplo de referência a esses aliases abaixo.

# Use o AliasProperty no lugar de um nome de propriedade real
PS51> $Svc = Get-Service -ServiceName 'BITS' #Objeto com o qual você está trabalhando
PS51> $Svc.Name
BITS
PS51> $Svc.RequiredServices

Você deve ver a seguinte saída. Note novamente que você está mantendo o código curto, limpo e conciso. A informação é a mesma, independentemente de usar o alias ou não:

Properties on the BITS service object

Métodos

Propriedades são apenas uma parte que cria um objeto; métodos também são um conceito importante para entender. Métodos são as ações que podem ser realizadas em um objeto. Assim como as propriedades, você pode descobrir métodos em um objeto usando o cmdlet Get-Member.

Para limitar a saída do Get-Member apenas a métodos, defina o valor do parâmetro MemberType para Método, como mostrado abaixo.

PS51> Get-Service | Get-Member -MemberType 'Method'
Methods on service objects

Como iniciante, você usará métodos muito menos frequentemente do que propriedades.

Outros Tipos de Membros

Propriedades, métodos e aliases não são os únicos tipos de membros que um objeto pode ter. No entanto, eles serão, de longe, o tipo mais comum de membros com os quais você estará trabalhando.

Para completar, abaixo estão alguns outros tipos de membros que você pode encontrar.

  • Script Property – Estes são usados para calcular valores de propriedade.
  • Note Property – Estes são usados para nomes de propriedade estáticos.
  • Conjuntos de Propriedades – Esses são como aliases que contêm exatamente o que o nome sugere; conjuntos de propriedades. Por exemplo, você criou uma propriedade personalizada chamada Specs para sua função Get-CompInfo. Specs é na verdade um subconjunto das propriedades Cpu, Mem, Hdd, IP. O objetivo principal dos conjuntos de propriedades é fornecer um único nome de propriedade para concatenar um grupo de propriedades.

Itambém é importante mencionar o conceito de eventos de objeto. Os eventos estão fora do escopo deste artigo.

Trabalhando com Objetos no PowerShell

Agora que você tem uma compreensão básica do que um objeto consiste, vamos começar a colocar a mão na massa e entrar em algum código.

Muitos comandos do PowerShell produzem saída, mas às vezes você não precisa ver toda essa saída. Você precisa limitar ou manipular essa saída de alguma forma. Felizmente, o PowerShell tem alguns comandos diferentes que permitem fazer exatamente isso.

Vamos começar com um exemplo de enumeração de todos os serviços no computador local usando o cmdlet Get-Service como mostrado abaixo. Você pode ver pela saída que muitos serviços diferentes (objetos) são retornados.

PS51> Get-Service -ServiceName *
Using a wildcard on ServiceName parameter

Controlando Propriedades do Objeto Retornado

Continuando com o exemplo do Get-Service, talvez você não precise ver cada propriedade. Em vez disso, você só precisa ver as propriedades Status e DisplayName. Para limitar as propriedades retornadas, você usaria o cmdlet Select-Object.

O cmdlet Select-Object “filtra” várias propriedades antes de serem retornadas para o pipeline do PowerShell. Para “filtrar” as propriedades do objeto antes de retorná-las, você pode usar o parâmetro Property e especificar um conjunto separado por vírgulas de uma ou mais propriedades para retornar.

Abaixo, você pode ver um exemplo de retorno apenas das propriedades Status e DisplayName.

PS51> Get-Service -ServiceName * | Select-Object -Property 'Status','DisplayName'
Showing the Status and DisplayName properties

Ordenando Objetos

Talvez você esteja construindo um relatório para mostrar serviços e seus status. Para facilitar a digestão da informação, você gostaria de ordenar os objetos retornados pelo valor da propriedade Status. Para fazer isso, você pode usar o cmdlet Sort-Object.

O cmdlet Sort-Object permite que você colete todos os objetos retornados e os apresente na ordem que você define.

Por exemplo, usando o parâmetro Property do Sort-Object, você pode especificar uma ou mais propriedades nos objetos recebidos de Get-Service para ordenar. O PowerShell passará cada objeto para o cmdlet Sort-Object e os retornará ordenados pelo valor da propriedade.

Aqui está um exemplo de retorno de todos os objetos de serviço ordenados por sua propriedade Status em ordem decrescente usando o parâmetro de comutação Descending do Sort-Object.

PS51> Get-Service -ServiceName * | Select-Object -Property 'Status','DisplayName' |
	Sort-Object -Property 'Status' -Descending
Using Sort-Object to sort service objects by Status in descending order

O pipe [ | ] no PowerShell é uma das técnicas de continuação de linha que você deve usar quando necessário. Use-o em vez de acentos graves.

Filtrando Objetos

Talvez você decida que não quer ver todos os serviços em uma máquina. Em vez disso, você precisa limitar a saída por critérios específicos. Uma maneira de filtrar o número de objetos retornados é usando o cmdlet Where-Object.

Enquanto o cmdlet Select-Object limita a saída de propriedades específicas, o cmdlet Where-Object limita a saída de objetos inteiros.

O cmdlet Where-Object é semelhante em função à cláusula WHERE SQL. Ele atua como um filtro da fonte original para retornar apenas certos objetos que correspondem a um critério específico.

Talvez você tenha decidido que só quer objetos retornados com um valor de propriedade Status de Running e apenas aqueles com um valor de propriedade DisplayName que começa com A.

Você pode ver no próximo trecho de código uma referência Where-Object foi inserida entre Select-Object e Sort-Object na ordem do pipeline. Usando um valor de scriptblock com uma condição obrigatória criada para cada objeto atender via parâmetro FilterScript, você pode criar qualquer tipo de consulta que desejar.

Confira o cmdlet Format-Table se quiser manipular como a saída é retornada para o console.

PS51> Get-Service * | Select-Object -Property 'Status','DisplayName' |
	Where-Object -FilterScript {$_.Status -eq 'Running' -and $_.DisplayName -like "Windows*" |
		Sort-Object -Property 'DisplayName' -Descending | Format-Table -AutoSize
Formatting object output

Contagem e Média dos Objetos Retornados

O comando Get-Service retorna muitos objetos diferentes. Usando o cmdlet Where-Object, você filtrou uma parte desses objetos, mas quantos? Apresentando o cmdlet Measure-Object.

O cmdlet Measure-Object é um comando do PowerShell que, entre outras operações matemáticas, pode contar quantos objetos ele recebe através do pipeline.

Talvez você queira saber quantos objetos são retornados no final da execução dos seus comandos combinados. Você pode redirecionar a saída final para o cmdlet Measure-Object para encontrar o número total de objetos retornados, como mostrado abaixo.

PS51> Get-Service * | Select-Object -Property 'Status','DisplayName' |
	Where-Object {$_.Status -eq 'Running' -and $_.DisplayName -like "Windows*" |
		Sort-Object -Property 'DisplayName' -Descending | Measure-Object

Assim que os comandos terminarem de processar, você verá, neste caso, que inicialmente foram retornados 21 objetos criados com o cmdlet Get-Service.

Finding the number of objects returned with Measure-Object

Talvez você esteja apenas procurando pelo total de objetos retornados. Como o comando Measure-Object retorna o total de objetos encontrados através da propriedade Count, você pode fazer referência novamente ao cmdlet Select-Object. Mas desta vez, retornando apenas a propriedade Count.

PS51> Get-Service * | Select-Object -Property 'Status','DisplayName' |
	Where-Object {$_.Status -eq 'Running' -and $_.DisplayName -like "Windows*" |
		Sort-Object -Property 'DisplayName' -Descending |
			Measure-Object |
				# Começamos novamente, filtrando primeiro, formatando por último
				Select-Object -Property 'Count'
Only returning the count property

Tomando ação em objetos com loops

Conforme cada objeto é processado pelo pipeline, você pode tomar uma ação em cada objeto com um loop. Existem diferentes tipos de loops no PowerShell, mas, mantendo-se com exemplos de pipeline, vamos olhar para o cmdlet ForEach-Object.

O cmdlet ForEach-Object permite que você tome uma ação em cada objeto que passa por ele. Esse comportamento é melhor explicado com um exemplo.

Continuando a usar um exemplo de Get-Service, talvez você queira encontrar todos os serviços em um computador Windows com um nome que comece com “Windows” e esteja em execução. Usando o cmdlet Where-Object, você pode criar as condições como fez anteriormente.

Where-Object -FilterScript {$_.DisplayName -Like "Windows*" -and $_.Status -eq 'Running'}

Mas agora, em vez de retornar objetos inteiros ou mesmo algumas propriedades, você gostaria de retornar a string <ServiceName> está em execução para cada objeto usando o código **Write-Host -ForegroundColor 'Yellow' <ServiceName> "está em execução".

Agora você está manipulando a saída e criando sua própria string. A única maneira de fazer isso é usar o cmdlet ForEach-Object conforme mostrado abaixo. Abaixo, você pode ver que para cada objeto retornado via Where-Object, o PowerShell executa o código Write-Host -ForegroundColor 'Yellow' $_.DisplayName "está em execução".

PS51> Get-Service -ServiceName * |
	Where-Object {$_.DisplayName -Like "Windows*" -and $_.Status -eq 'Running'} | 
		Foreach-Object {
			Write-Host -ForegroundColor 'Yellow' $_.DisplayName "is running"
		}
Filtering by property with Where-Object

O cmdlet ForEach-Object é útil de muitas maneiras. Como exemplo, você poderia adicionar lógica adicional para enumerar cada objeto de serviço encontrado e, com base em um valor de propriedade, alterar a cor e o texto da string de saída ou até mesmo realizar uma ação adicional, como iniciar um serviço parado.

Imagine as possibilidades que isso oferece a você! Com um pouco de pensamento e planejamento, você poderia criar um script que execute um único comando em muitos objetos sem esforço.

Comparando Objetos

Às vezes, você precisa olhar para dois objetos e comparar os valores das propriedades.

Brazilian Portuguese
Talvez você tenha dois sistemas em sua rede que sejam quase idênticos. No entanto, você está enfrentando o que espera ser um problema de configuração com um serviço em um dos dois sistemas.

Você conclui que, como esses sistemas estão em partes diferentes de sua rede, será necessário usar comandos remotos para coletar as informações em uma sessão do PowerShell. Você abre seu editor favorito e cria um script. Este script, como você pode ver abaixo, se conecta a dois servidores diferentes e enumera todos os processos em cada um deles.

$A = 'Svr01a.contoso.com'
$B = 'Svr02b.contoso.com'

$ProcA = Invoke-Command -Computername $A -Scriptblock {Get-Process -Name *}
$ProcB = Invoke-Command -ComputerName $B -Scriptblock {Get-Process -Name *}

Agora você capturou todos os processos em cada computador nas variáveis $ProcA e $ProcB. Agora você precisa compará-los. Você poderia olhar manualmente através de cada conjunto de processos, ou poderia fazer isso da maneira fácil usando um cmdlet chamado Compare-Object.

Compare-Object permite que você compare os valores das propriedades de dois objetos diferentes. Este cmdlet lê cada propriedade em cada objeto, examina seus valores e depois retorna o que é diferente, por padrão, e também o que é igual.

Para usar Compare-Object, especifique um parâmetro ReferenceObject e um parâmetro DifferenceObject, fornecendo cada objeto como os valores dos parâmetros, como mostrado abaixo.

Compare-Object -ReferenceObject $ProcA -DifferenceObject $ProcB

Por padrão, Compare-Object só retornará as diferenças nos objetos indicados pela propriedade SideIndicator. Os símbolos ou indicadores laterais usados são >, <, & = para mostrar as correspondências entre os objetos sendo comparados.

Running Compare-Object

Você pode usar o parâmetro de switch IncludeEqual com Compare-Object para retornar as propriedades do objeto que são iguais. Se isso ocorrer, você verá == como indicador lateral. Da mesma forma, você pode usar ExcludeDifferent para excluir diferenças.

O cmdlet Compare-Object é um cmdlet muito útil. Se desejar aprender mais, não deixe de visitar a documentação online.

Trabalhando com Objetos Personalizados

Agora que você tem uma boa compreensão do que são objetos e como trabalhar com eles, é hora de criar seus próprios objetos!

Criando Objetos Personalizados a partir de Hashtables

Uma maneira de criar seus próprios objetos é usando hashtables. Hashtables são conjuntos de pares chave/valor, exatamente o que você precisa para criar propriedades para um objeto.

Vamos começar criando um objeto personalizado do PowerShell com algumas chave/valor usando uma hashtable. No exemplo abaixo, você está criando uma hashtable. Esta hashtable está representando um único objeto e suas propriedades. Depois que a hashtable $CarHashtable foi definida, você pode usar o acelerador de tipo PsCustomObject type accelerator.

O tipo acelerador pscustomobject é uma maneira rápida de criar uma instância da classe pscustomobject. Esse comportamento é chamado de casting.

No final do trecho de código abaixo, você terá um objeto ($CarObject) do tipo pscustomobject com cinco propriedades atribuídas a ele.

## Definir a hashtable
$CarHashtable = @{
	Brand      = 'Ford'
	Style      = 'Truck'
	Model      = 'F-150'
	Color      = 'Red'
	Drivetrain = '4x4'
}

## Criar um objeto
$CarObject = [PsCustomObject]$CarHashTable

Alternativamente, você também pode usar o cmdlet New-Object. Usando a mesma hashtable, em vez de usar o acelerador de tipo pscustomobject, você poderia fazer isso da forma longa com New-Object. Um exemplo disso é mostrado abaixo.

$CarHashtable = @{
	Brand      = 'Ford'
	Style      = 'Truck'
	Model      = 'F-150'
	Color      = 'Red'
	Drivetrain = '4x4'
}
#Criar um objeto
$CarObject = New-Object -TypeName PsObject -Properties $CarHashtable

Quando $CarObject é criado, você pode ver abaixo que pode fazer referência a cada uma das propriedades como se viesse de um cmdlet PowerShell integrado como Get-Service.

Inspecting object properties

Adicionando e removendo propriedades

Não só é possível criar objetos personalizados, mas também adicioná-los. Lembra-se de usar o cmdlet Get-Member? Get-Member tem um relativo chamado Add-Member. O cmdlet Add-Member não enumera membros, ele adiciona eles.

Usando o objeto personalizado previamente criado como exemplo, talvez você queira adicionar uma propriedade de ano do modelo a esse objeto. Você pode fazer isso encaminhando um objeto para Add-Member especificando:

  • O tipo de membro (neste caso, um simples NoteProperty)
  • O nome da propriedade (Ano)
  • O valor da propriedade (Valor)

Você pode ver um exemplo disso abaixo.

PS51> $CarObject | Add-Member -MemberType NoteProperty -Name 'Year' -Value '2010'

Você pode ver abaixo novamente que aparece como qualquer outra propriedade.

Adding and viewing a new property

Você pode usar técnicas semelhantes para adicionar muitos tipos diferentes de membros. Se você quiser explorar mais por conta própria, dê uma olhada na documentação Adicionar-Membro.

Você também pode remover facilmente um membro de um objeto. Embora não haja um cmdlet Remover-Membro, você ainda pode fazer isso chamando o método Remover() no objeto, como mostrado abaixo. Você aprenderá sobre métodos na próxima seção.

PS51> $CarObject.psobject.properties.remove('Drivetrain')

Introdução Rápida aos Métodos

Ao longo deste artigo, você trabalhou com propriedades. Você leu valores de propriedade, criou suas próprias propriedades e as adicionou e removeu. Mas você realmente não fez muito com o ambiente. Você não mudou nada no servidor. Vamos tomar alguma ação com métodos.

Os métodos realizam algum tipo de ação. Objetos armazenam informações enquanto os métodos tomam ações.

Por exemplo, você pode estar ciente do comando Parar-Serviço. Este comando para um serviço do Windows. Para fazer isso, você pode enviar um objeto de Obter-Serviço diretamente para Parar-Serviço para que isso aconteça.

Você pode ver abaixo um exemplo de como parar o serviço BITS. Este exemplo para o serviço BITS e então verifica o status para garantir que ele está parado. Você realizou duas ações com cmdlets; parar o serviço e verificar o status.

PS51> Get-Service -ServiceName 'BITS' | Stop-Service
PS51> Get-Service -ServiceName 'BITS'

Em vez de executar Get-Service duas vezes e executar um comando separado, Stop-Service, você pode aproveitar métodos que estão incorporados nos objetos de serviço. Muitos objetos têm métodos. Neste caso, Stop-Service e aquela segunda referência Get-Service nem mesmo é necessária.

Running commands to stop and start a service

Ao invocar métodos no próprio objeto de serviço, você pode parar e obter o status atualizado, tudo usando um único objeto. Abaixo você pode ver isso em ação. Note que ao usar os métodos Stop() e Start(), você pode manipular o serviço como os comandos fizeram.

Para garantir que o valor da propriedade Status esteja atualizado após a alteração do status do serviço, você pode invocar o método Refresh(), que age como outra chamada de comando Get-Service.

## Parar BITS na máquina local
$Svc = Get-Service -ServiceName 'BITS' #Objeto com o qual você está trabalhando
$Svc.Stop() #Método / ação que você está executando
$Svc.Refresh() #Método / ação que você está executando
$Svc.Status #Propriedade

#Iniciar BITS na máquina local
$Svc = Get-Service -ServiceName 'BITS' #Objeto com o qual você está trabalhando
$Svc.Start() #Método / ação que você está executando
$Svc.Refresh() #Método / ação que você está executando
$Svc.Status #Propriedade

Você deve ver a seguinte saída:

Executing methods on the service object

Para obter mais informações sobre métodos, consulte o tópico de ajuda sobre_Métodos.

Conclusão

Há muitas coisas que você pode fazer com objetos no PowerShell. Este artigo foi apenas um começo para ajudá-lo a aprender sobre eles. No artigo, você aprendeu alguns conceitos básicos sobre o que são objetos, como agir, manipulá-los e criá-los. Você viu alguns cenários diferentes que mostraram como realizar essas tarefas com exemplos de código. Mantenha a calma e aprenda PowerShell. Obrigado por ler!

Source:
https://adamtheautomator.com/powershell-objects/