A saída de texto dos comandos na janela do interpretador do PowerShell é apenas uma maneira de exibir informações em um formato legível por humanos. De fato, o ambiente está focado no trabalho com objetos: cmdlets e funções os recebem na entrada e retornam na saída , e os tipos de variáveis disponíveis no modo interativo e nos scripts são baseados nas classes .NET. No quarto artigo do ciclo, estudaremos o trabalho com objetos em mais detalhes.Índice:
PowerShellForEach-Object, Group-Object Measure-Object.NET COM (New-Object)PSCustomObjectPowerShell
Lembre-se de que um objeto é uma coleção de campos de dados (propriedades, eventos etc.) e seus métodos de processamento (métodos). Sua estrutura é determinada pelo tipo, que geralmente é baseado nas classes usadas na plataforma .NET Core unificada. Também é possível trabalhar com objetos COM, CIM (WMI) e ADSI. São necessárias propriedades e métodos para executar várias ações nos dados; além do PowerShell, os objetos podem ser passados como argumentos para funções e cmdlets, atribuídos seus valores às variáveis e também há um mecanismo para compor comandos (pipeline ou pipeline). Cada comando no pipeline passa sua saída para o próximo por turno - objeto por objeto. Para processamento, você pode usar cmdlets compilados ou criar suas próprias funções avançadasrealizar várias manipulações com objetos no pipeline: filtrar, classificar, agrupar e até alterar sua estrutura. A transferência de dados neste formulário tem uma séria vantagem: a equipe receptora não precisa analisar o fluxo de bytes (texto), todas as informações necessárias são facilmente extraídas consultando as propriedades e métodos correspondentes.Ver estrutura do objeto
Por exemplo, execute o cmdlet Get-Process, que permite obter informações sobre os processos em execução no sistema:
Ele exibe alguns dados de texto formatados que não dão uma idéia das propriedades dos objetos retornados e seus métodos. Para ajustar a saída, você precisa aprender a examinar a estrutura dos objetos, e o cmdlet Get-Member nos ajudará com isso:Get-Process | Get-Member
Aqui já vemos o tipo e a estrutura e, com a ajuda de parâmetros adicionais, podemos, por exemplo, exibir apenas as propriedades do objeto que entrou na entrada:Get-Process | Get-Member -MemberType Property
Esse conhecimento será necessário para resolver tarefas administrativas de maneira interativa ou para escrever seus próprios scripts: por exemplo, para obter informações sobre processos interrompidos pela propriedade Responding.Filtragem de Objetos
O PowerShell permite canalizar objetos que atendem a uma condição específica:Where-Object { }
O resultado da execução do bloco de scripts entre colchetes do operador deve ser um valor lógico. Se for verdadeiro ($ true), o objeto que inseriu o cmdlet Where-Object será transmitido pelo pipeline, caso contrário (o valor $ false) será excluído. Por exemplo, listamos os serviços interrompidos do Windows Server, ou seja, aqueles com a propriedade Status definida como Parado:Get-Service | Where-Object {$_.Status -eq "Stopped"}
Aqui vemos novamente a representação textual, mas se você deseja entender o tipo e a estrutura interna dos objetos que passam pelo pipeline, é fácil:Get-Service | Where-Object {$_.Status -eq "Stopped"} | Get-Member

Classificar objetos
Ao canalizar objetos, geralmente é necessário classificá-los. Os nomes de propriedades (chaves de classificação) são passados para o cmdlet Sort-Object e retornam objetos ordenados por seus valores. A saída dos processos em execução pode ser facilmente classificada pelo tempo gasto do processador (propriedade da CPU):Get-Process | Sort-Object –Property cpu
O parâmetro -Property pode ser omitido ao chamar o cmdlet Sort-Object - ele é usado por padrão. Para classificação inversa, use o parâmetro -Descending:Get-Process | Sort-Object cpu -Descending

Seleção de objetos e suas partes
O cmdlet Select-Object permite selecionar um número específico de objetos no início ou no final de um pipeline usando os parâmetros -First ou -Last. Com ele, você pode selecionar objetos únicos ou determinadas propriedades, bem como criar novos objetos com base em tais itens. Vamos ver o trabalho do cmdlet usando exemplos simples.O comando a seguir exibe informações sobre 10 processos que consomem a quantidade máxima de RAM (propriedade WS):Get-Process | Sort-Object WS -Descending | Select-Object -First 10
Você pode selecionar apenas determinadas propriedades dos objetos que passam pelo pipeline e criar novas com base em:Get-Process | Select-Object ProcessName, Id -First 1
Como resultado do pipeline, obteremos um novo objeto, cuja estrutura será diferente da estrutura retornada pelo cmdlet Get-Process. Verificaremos isso usando Get-Member:Get-Process | Select-Object ProcessName, Id -First 1 | Get-Member
Observe que Select-Object retorna um único objeto (-First 1), que possui apenas dois campos especificados por nós: seus valores foram copiados do primeiro objeto passado para o pipeline com o cmdlet Get-Process. Usando Select-Object, uma das maneiras de criar objetos nos scripts do PowerShell é baseada:$obj = Get-Process | Select-Object ProcessName, Id -First 1
$obj.GetType()
Usando Select-Object, você pode adicionar propriedades calculadas a objetos que devem ser representados como uma tabela de hash . Nesse caso, o valor de sua primeira chave corresponde ao nome da propriedade e o valor da segunda corresponde ao valor da propriedade para o elemento atual do pipeline:Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}}
Vejamos a estrutura dos objetos que passam pelo pipeline:Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} | Get-Member

ForEach-Object, Group-Object e Measure-Object
Existem outros cmdlets para trabalhar com objetos. Por exemplo, falaremos sobre os três mais úteis:ForEach-Object permite executar o código do PowerShell para cada objeto no pipeline:ForEach-Object { }
Objeto de grupo agrupa objetos por valor da propriedade:Group-Object PropertyName
Se você executá-lo com o parâmetro -NoElement, poderá descobrir o número de elementos nos grupos.O Measure-Object agrega vários parâmetros de resumo pelos valores dos campos dos objetos no pipeline (calcula a soma e também encontra o valor mínimo, máximo ou médio):Measure-Object -Property PropertyName -Minimum -Maximum -Average -Sum
Normalmente, os cmdlets considerados são usados interativamente e os scripts geralmente criam funções com os blocos Begin, Process e End.Criando objetos .NET e COM (novo objeto)
Existem muitos componentes de software com interfaces .NET Core e COM que são úteis para administradores de sistema. Usando a classe System.Diagnostics.EventLog, você pode gerenciar os logs do sistema diretamente do Windows PowerShell. Vejamos um exemplo de criação de uma instância dessa classe usando o cmdlet New-Object com o parâmetro -TypeName:New-Object -TypeName System.Diagnostics.EventLog
Como não especificamos um log de eventos específico, a instância resultante da classe não contém dados. Para alterar isso, durante sua criação, você deve chamar o método construtor especial usando o parâmetro -ArgumentList. Se quisermos acessar o log do aplicativo, passe a string "Application" como argumento para o construtor:$AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
$AppLog
Observe: salvamos a saída do comando na variável $ AppLog. Embora os pipelines sejam comumente usados no modo interativo, os scripts geralmente exigem a manutenção de uma referência a objeto. Além disso, as principais classes do .NET Core estão contidas no espaço para nome do sistema: o PowerShell pesquisa por padrão os tipos especificados nele, portanto, escrever Diagnostics.EventLog em vez de System.Diagnostics.EventLog está bastante correto.Para trabalhar com o diário, você pode consultar os métodos apropriados:$AppLog | Get-Member -MemberType Method
Digamos que seja limpo usando o método Clear () com direitos de acesso:$AppLog.Clear()
O cmdlet New-Object também é usado para trabalhar com componentes COM. Existem muitos deles - das bibliotecas fornecidas com o servidor de script do Windows aos aplicativos ActiveX, como, por exemplo, o Internet Explorer. Para criar um objeto COM, você precisa especificar o parâmetro -ComObject com o identificador de programa ProgId da classe desejada:New-Object -ComObject WScript.Shell
New-Object -ComObject WScript.Network
New-Object -ComObject Scripting.Dictionary
New-Object -ComObject Scripting.FileSystemObject
Para criar seus próprios objetos com uma estrutura arbitrária, o uso de Novo Objeto parece muito arcaico e complicado; esse cmdlet é usado para trabalhar com componentes de software externos ao PowerShell. Nos artigos subseqüentes, esse problema será discutido em mais detalhes. Além dos objetos .NET e COM, também aprenderemos sobre objetos CIM (WMI) e ADSI.Chamando métodos estáticos
Não é possível criar instâncias de algumas classes do .NET Core: elas incluem System.Environment e System.Math. Eles são estáticos e contêm apenas propriedades e métodos estáticos. Em essência, são bibliotecas de referência usadas sem criar objetos. Você pode se referir a uma classe estática por meio de um literal, colocando o nome do tipo entre colchetes. Além disso, se você observar a estrutura do objeto usando Get-Member, veremos o tipo System.RuntimeType em vez de System.Environment:[System.Environment] | Get-Member
Para visualizar apenas elementos estáticos, é necessário chamar Get-Member com o parâmetro -Static (preste atenção ao tipo de objeto):[System.Environment] | Get-Member -Static
Para acessar propriedades e métodos estáticos, dois pontos consecutivos são usados em vez de um ponto após um literal:[System.Environment]::OSVersion
Ou$test=[System.Math]::Sqrt(25)
$test
$test.GetType()

Tipo PSCustomObject
Entre os muitos tipos de dados disponíveis no PowerShell, vale mencionar o PSCustomObject, projetado para armazenar objetos com uma estrutura arbitrária. A criação de um objeto desse tipo usando o cmdlet New-Object é considerada uma maneira clássica, mas complicada e obsoleta:$object = New-Object –TypeName PSCustomObject -Property @{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'}
Vejamos a estrutura do objeto:$object | Get-Member
A partir do PowerShell 3.0, outra sintaxe está disponível:$object = [PSCustomObject]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
Você pode acessar os dados de uma das maneiras equivalentes:$object.Name
$object.'Name'
$value = 'Name'
$object.$value
Aqui está um exemplo de conversão de uma tabela de hash existente em um objeto:$hash = @{'Name'='Ivan Danko'; 'City'='Moscow'; 'Country'='Russia'}
$hash.GetType()
$object = [pscustomobject]$hash
$object.GetType()
Uma das desvantagens de objetos desse tipo é que a ordem de suas propriedades pode mudar. Para evitar isso, você deve usar o atributo [ordenado]:$object = [PSCustomObject][ordered]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
Existem outras opções para criar um objeto: acima, examinamos o uso do cmdlet Select-Object . Resta lidar com a adição e remoção de elementos. Fazer isso para o objeto do exemplo anterior é bastante simples:$object | Add-Member –MemberType NoteProperty –Name Age –Value 33
$object | Get-Member
O cmdlet Add-Member permite adicionar não apenas propriedades, mas também métodos ao objeto $ object criado anteriormente usando a construção "-MemberType ScriptMethod":$ScriptBlock = {
}
$object | Add-Member -Name "MyMethod" -MemberType ScriptMethod -Value $ScriptBlock
$object | Get-Member
Nota: para armazenar o código para o novo método, usamos a variável $ ScriptBlock do tipo ScriptBlock.
Para remover propriedades, use o método apropriado:$object.psobject.properties.remove('Name')
Criando suas próprias classes
O PowerShell 5.0 apresenta a capacidade de definir classes usando a sintaxe da característica para linguagens de programação orientadas a objetos. A palavra de serviço Class destina-se a isso, após o qual você deve especificar o nome da classe e descrever seu corpo entre colchetes do operador:class MyClass
{
}
Esse é um verdadeiro tipo de .NET Core, cujo corpo descreve suas propriedades, métodos e outros elementos. Considere um exemplo de uma definição de classe simples:class MyClass
{
[string]$Name
[string]$City
[string]$Country
}
Para criar um objeto (uma instância de uma classe), use o cmdlet New-Object ou um literal do tipo [MyClass] e o novo método pseudo - estático (construtor padrão):$object = New-Object -TypeName MyClass
ou$object = [MyClass]::new()
Vamos analisar a estrutura do objeto:$object | Get-Member
Não se esqueça do escopo: você não pode se referir ao nome do tipo como uma sequência ou usar um literal de tipo fora do script ou módulo no qual a classe está definida. Ao mesmo tempo, as funções podem retornar instâncias da classe (objetos) que estarão disponíveis fora do módulo ou script.Após criar o objeto, preencha suas propriedades:$object.Name = 'Ivan Danko'
$object.City = 'Moscow'
$object.Country = 'Russia'
$object
Observe que na descrição da classe não apenas os tipos de propriedade são definidos, mas também seus valores padrão:class Example
{
[string]$Name = 'John Doe'
}
A descrição do método de classe se assemelha à descrição de uma função, mas sem usar a função word da função. Como na função, os parâmetros são passados para os métodos, se necessário:class MyClass
{
[string]$Name
[string]$City
[string]$Country
Smile([bool]$param1)
{
If($param1) {
Write-Host ':)'
}
}
}
Agora, o representante da nossa turma sabe sorrir:$object = [MyClass]::new()
$object.Smile($true)
Os métodos podem ser sobrecarregados; além disso, a classe possui propriedades e métodos estáticos , além de construtores cujos nomes coincidem com o nome da própria classe. Uma classe definida em um script ou módulo do PowerShell pode servir como base para outra - é assim que a herança é implementada. Ao mesmo tempo, o uso de classes .NET existentes é permitido como base:class MyClass2 : MyClass
{
}
[MyClass2]::new().Smile($true)
Nossa descrição do trabalho com objetos no PowerShell não é exaustiva. Nas publicações a seguir, tentaremos aprofundá-lo com exemplos práticos: o quinto artigo da série será dedicado aos problemas de integração do PowerShell com componentes de software de terceiros. Partes anteriores podem ser encontradas nos links abaixo.
1: Windows PowerShell2: Windows PowerShell3: ,