A saída de texto dos comandos na janela do interpretador do PowerShell é apenas uma forma de exibir informações em um formato adequado à percepção humana. Na verdade quarta-feira
Sumário:
Objetos no PowerShell
Lembremos que um objeto é uma coleção de campos de dados (propriedades, eventos, etc.) e métodos para processá-los (métodos). Sua estrutura é especificada por um tipo, que geralmente é baseado em classes usadas na plataforma unificada .NET Core. Também é possível trabalhar com objetos COM, CIM (WMI) e ADSI. Propriedades e métodos são necessários para executar várias ações nos dados; além disso, no PowerShell, os objetos podem ser passados como argumentos para funções e cmdlets, atribuídos seus valores a variáveis, e também há
Visualizando a estrutura dos objetos
Por exemplo, vamos executar o cmdlet Get-Process, que permite obter informações sobre os processos em execução no sistema:
Ele exibirá alguns dados de texto formatados que não dão nenhuma ideia sobre as propriedades dos objetos retornados e seus métodos. Para ajustar a saída, precisamos aprender como 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 incluído na entrada:
Get-Process | Get-Member -MemberType Property
Esse conhecimento será necessário para resolver problemas de administração de forma interativa ou para escrever seus próprios scripts: por exemplo, para obter informações sobre processos travados usando a propriedade Responding.
Filtrando objetos
O PowerShell permite que objetos que atendam a uma determinada condição sejam passados por um pipeline:
Where-Object { блок сценария }
O resultado da execução do bloco de script entre parênteses deve ser um valor booleano. Se for verdadeiro ($true), o objeto inserido no cmdlet Where-Object será passado ao longo do pipeline; caso contrário, ($false) será excluído. Por exemplo, vamos exibir uma lista de serviços interrompidos do Windows Server, ou seja, aqueles cuja propriedade Status está definida como “Parado”:
Get-Service | Where-Object {$_.Status -eq "Stopped"}
Aqui novamente vemos uma representação textual, mas se você quiser entender o tipo e a estrutura interna dos objetos que passam pelo pipeline não é difícil:
Get-Service | Where-Object {$_.Status -eq "Stopped"} | Get-Member
Classificando objetos
Ao processar objetos em pipeline, geralmente é necessário classificá-los. O cmdlet Sort-Object recebe os nomes das propriedades (chaves de classificação) e retorna objetos ordenados por seus valores. É fácil classificar a saída dos processos em execução pelo tempo gasto na CPU (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 reversa, use o parâmetro -Decrescente:
Get-Process | Sort-Object cpu -Descending
Selecionando 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 sua ajuda, você pode selecionar objetos únicos ou determinadas propriedades, bem como criar novos objetos com base neles. Vejamos como o cmdlet funciona usando exemplos simples.
O comando a seguir exibe informações sobre os 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 de objetos que passam pelo pipeline e criar novas com base nelas:
Get-Process | Select-Object ProcessName, Id -First 1
Como resultado do pipeline, receberemos um novo objeto, cuja estrutura será diferente da estrutura retornada pelo cmdlet Get-Process. Vamos verificar 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 dos campos que especificamos: seus valores foram copiados do primeiro objeto passado para o pipeline pelo cmdlet Get-Process. Uma das maneiras de criar objetos em scripts do PowerShell é baseada no uso de Select-Object:
$obj = Get-Process | Select-Object ProcessName, Id -First 1
$obj.GetType()
Usando Select-Object, você pode adicionar propriedades computadas a objetos que precisam ser representados como
Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}}
Vejamos a estrutura dos objetos que passam pela esteira:
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. Como exemplo, vamos falar dos 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 de propriedade:
Group-Object PropertyName
Se você executá-lo com o parâmetro -NoElement, poderá descobrir o número de elementos nos grupos.
Medida-Objeto agrega vários parâmetros de resumo por valores de campo de objeto 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 discutidos são usados de forma interativa e geralmente criados em scripts.
Criando objetos .NET e COM (New-Object)
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 logs do sistema diretamente do Windows PowerShell. Vejamos um exemplo de criação de uma instância desta 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, você precisa chamar um método construtor especial durante sua criação usando o parâmetro -ArgumentList. Se quisermos acessar o log da aplicação, devemos passar a string "Application" como argumento para o construtor:
$AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
$AppLog
Observe que salvamos a saída do comando na variável $AppLog. Embora os pipelines sejam comumente usados no modo interativo, a escrita de scripts geralmente requer a manutenção de uma referência a um objeto. Além disso, as classes principais do .NET Core estão contidas no namespace System: o PowerShell, por padrão, procura tipos especificados nele, portanto, escrever Diagnostics.EventLog em vez de System.Diagnostics.EventLog é bastante correto.
Para trabalhar com o log, você pode usar os métodos apropriados:
$AppLog | Get-Member -MemberType Method
Digamos que seja limpo pelo método Clear() se houver direitos de acesso:
$AppLog.Clear()
O cmdlet New-Object também é usado para trabalhar com componentes COM. Existem muitos deles - desde bibliotecas fornecidas com o servidor de scripts do Windows até aplicativos ActiveX, como o Internet Explorer. Para criar um objeto COM, você precisa definir o parâmetro -ComObject com o ProgId programático 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, usar New-Object parece muito arcaico e complicado; esse cmdlet é usado para trabalhar com componentes de software externos ao PowerShell. Em artigos futuros este assunto será discutido com mais detalhes. Além dos objetos .NET e COM, também exploraremos objetos CIM (WMI) e ADSI.
Chamando métodos estáticos
Algumas classes do .NET Core não podem ser instanciadas, incluindo System.Environment e System.Math. Eles são
[System.Environment] | Get-Member
Para visualizar apenas membros estáticos, chame Get-Member com o parâmetro -Static (observe o tipo de objeto):
[System.Environment] | Get-Member -Static
Para acessar propriedades e métodos estáticos, use dois dois-pontos consecutivos em vez de um ponto após o literal:
[System.Environment]::OSVersion
Ou
$test=[System.Math]::Sqrt(25)
$test
$test.GetType()
Digite PSCustomObject
Dentre os inúmeros tipos de dados disponíveis no PowerShell, vale destacar o PSCustomObject, projetado para armazenar objetos com estrutura arbitrária. Criar tal objeto usando o cmdlet New-Object é considerado uma forma clássica, mas complicada e desatualizada:
$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 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 [ordered]:
$object = [PSCustomObject][ordered]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
Existem outras opções para criar um objeto: acima vimos usando o cmdlet
$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 a um objeto $ criado anteriormente usando a construção "-MemberType ScriptMethod":
$ScriptBlock = {
# код
}
$object | Add-Member -Name "MyMethod" -MemberType ScriptMethod -Value $ScriptBlock
$object | Get-Member
Observe que usamos a variável $ScriptBlock do tipo ScriptBlock para armazenar o código do novo método.
Para remover propriedades, use o método correspondente:
$object.psobject.properties.remove('Name')
Criando suas próprias aulas
O PowerShell 5.0 introduziu a capacidade de definir
class MyClass
{
# тело класса
}
Este é um tipo verdadeiro do .NET Core, com um corpo que descreve suas propriedades, métodos e outros elementos. Vejamos um exemplo de definição da classe mais simples:
class MyClass
{
[string]$Name
[string]$City
[string]$Country
}
Para criar um objeto (instância de classe), use o cmdlet
$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 a um nome de tipo como uma string ou usar um tipo literal fora do script ou módulo no qual a classe está definida. Neste caso, as funções podem retornar instâncias de classe (objetos) que estarão acessí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 a descrição da classe especifica não apenas os tipos de propriedades, mas também seus valores padrão:
class Example
{
[string]$Name = 'John Doe'
}
A descrição de um método de classe se assemelha à descrição de uma função, mas sem usar a palavra de função. Como em uma função, os parâmetros são passados aos 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 pode sorrir:
$object = [MyClass]::new()
$object.Smile($true)
Os métodos podem ser sobrecarregados; além disso, uma classe tem
class MyClass2 : MyClass
{
#тело нового класса, базовым для которого является MyClass
}
[MyClass2]::new().Smile($true)
Nossa descrição de como trabalhar 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 às questões de integração do PowerShell com componentes de software de terceiros. As partes anteriores podem ser encontradas nos links abaixo.
Fonte: habr.com