A segunda parte da série abordou os conceitos básicos da linguagem de programação PowerShell, mas agora vale a pena descobrir como usar o código nele escrito para tarefas administrativas. A maneira mais óbvia de fazer isso é executar o script. Além disso, é possível criar seus próprios cmdlets.Índice:
Parâmetros posicionaisBloco Param ()Atributos de parâmetro adicionaisPassando parâmetros pelo pipelineEstrutura do corpo da funçãoAtributo [CmdletBinding ()] e funções avançadasMódulos de script e criação de cmdletsParâmetros posicionais
Em scripts e funções, você pode passar parâmetros posicionais (argumentos) cujos valores são gravados na variável interna $ args. Essa matriz unidimensional não requer declaração prévia e seu escopo é limitado a um script ou função. Por exemplo, execute o script mais simples:Write-Host " :" $args.count
Write-Host ":" $args
Nas funções, os parâmetros posicionais são usados da mesma maneira:function Print-Args {
Write-Host " :" $args.count
Write-Host " 0:" $args[0]
Write-Host " 1:" $args[1]
}
Print-Args “Zero” “One”Observe que, ao chamar Print-Args, não colocamos vírgula entre os parâmetros: não é um array que é passado para a função, mas valores individuais que são gravados no array unidimensional $ args - seu escopo é limitado pelo corpo da função.
O método descrito acima permite transferir qualquer número de parâmetros para um script ou função, mas ao chamar você deve seguir a ordem de sua sequência e pode acessá-los apenas pelo índice da matriz - isso nem sempre é conveniente.Bloco Param ()
Em scripts e funções, é muito mais conveniente usar parâmetros nomeados. Em um artigo anterior, falamos sobre uma maneira de descrevê-los:function test ($arg0, ..., $argN)
{
}
Uma sintaxe semelhante é familiar para os desenvolvedores, mas quando uma função é chamada, os parâmetros (se houver) são separados por espaços e não são colocados entre parênteses - uma certa dissonância surge. Essa é a especificidade das linguagens do shell: para trabalhar com o shell no modo interativo, os espaços entre os valores são muito mais convenientes. A chamada de teste ($ value0) também está correta, mas o parâmetro nesse caso é a expressão inteira entre parênteses, ou seja, ($ value0) em vez de $ value0 . Passando dessa maneira vários parâmetros não funcionarão. Como resultado da chamada de teste ($ value0, $ value1), a função receberá apenas um - uma matriz de dois elementos com os valores $ value0 e $ value1 .A Microsoft Corporation recomenda o uso do bloco Param () - essa sintaxe é mais universal e permite especificar não apenas argumentos de função, mas também parâmetros de script:param (
$arg0, $arg1
)
Write-Host $arg0 $arg1
No corpo da função, fica assim:function test {
param (
$arg0, $arg1
)
}
Se a lista de argumentos da função for pequena, o bloco Param () desorganiza apenas o design, mas em muitos casos torna o código mais legível e é, entre outras coisas, um elemento de um bom estilo de programação.Atributos de parâmetro adicionais
Ao descrever argumentos de função ou parâmetros de script, seus atributos adicionais podem ser configurados. O exemplo mais simples é uma instalação forçada do tipo:param([int]$arg0)
oufunction test ([int]$arg0) {
}
Além da conversão de tipo, você pode usar o atributo [parameter ()]:param(
[parameter(Argument1=value1, Argument2=value2)]
$ParameterName
)
Com sua ajuda, é fácil tornar o parâmetro obrigatório. Preste atenção ao uso simultâneo de vários atributos - nesse caso, eles se seguem:param([parameter(Mandatory=$true)][int]$arg0)
oufunction test ([parameter(Mandatory=$true)][int]$arg0) {
}
oufunction test {
parameter([parameter(Mandatory=$true)][int]$arg0)
}
A posição permite especificar a ordem do parâmetro (por padrão, corresponde à ordem da declaração):param(
[parameter(Mandatory=$true, Position=0)]
[int]
$arg0,
[parameter(Position=1)]
[string]
$arg1,
[parameter(Position=2)]
[array]
$arg2
)
O atributo [Parameter ()] possui outros argumentos, cuja lista completa está disponível no site da Microsoft. Outros atributos são descritos lá, com a ajuda dos quais você pode validar os valores passados, verificá-los usando expressões regulares, etc. Aqui estão alguns:[Alias ()] define um alias para o parâmetro:param(
[parameter(Mandatory=$true)]
[alias("ARG","ArgumentName")]
[string[]]
$arg0
)
O operador de conversão [string []] significa que o valor do parâmetro é uma matriz de string.[AllowNull ()] permite $ null como um parâmetro necessário:param(
[parameter(Mandatory=$true)]
[AllowNull()]
[string]
$arg0
)
[AllowEmptyString ()] permite uma string vazia como um parâmetro necessário:param(
[parameter(Mandatory=$true)]
[AllowEmptyString()]
[string]
$arg0
)
[AllowEmptyCollection ()] permite uma matriz vazia como um parâmetro necessário:param(
[parameter(Mandatory=$true)]
[AllowEmptyCollection()]
[string[]]
$arg0
)
Validação [ValidatePattern ()] usando uma expressão regular:param(
[parameter(Mandatory=$true)]
[ValidatePattern("[0-9][0-9][0-9][0-9]")]
[string[]]
$arg0
)
[ValidateLength ()] verifica o comprimento de um parâmetro de string:param(
[parameter(Mandatory=$true)]
[ValidateLength(1,10)]
[string]
$arg0
)
Passando parâmetros pelo pipeline
No primeiro artigo da série, falamos sobre a possibilidade de transferir dados para cmdlets por meio de um pipeline. No PowerShell, cmdlets e funções retornam objetos ou matrizes de objetos (resultados de instruções) e também os recebem na entrada. Para ver isso, preparamos um dos cmdlets usando Get-Help:Get-Help Stop-Process -Parameter Name
Por meio do pipeline, você pode aceitar valores de parâmetros para os quais os atributos correspondentes estão definidos (ByValue e / ou ByPropertyName). No primeiro caso, o parâmetro será correspondido com um objeto recebido através do pipeline, desde que seu tipo corresponda ao esperado. No segundo parâmetro, o valor será a propriedade do objeto recebido cujo nome corresponde ao nome ou alias deste parâmetro. Para definir os atributos, use [parameter ()] com os argumentos booleanos ValueFromPipeline e ValueFromPipelineByPropertyName, cujo valor padrão é $ false:param(
[parameter(Mandatory=$true,
ValueFromPipeline=$true)]
[string[]]
$Name
)
ouparam(
[parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true)]
[string[]]
$Name
)
ValueFromPipelineByPropertyName geralmente é usado, se necessário, para passar vários parâmetros para que não haja confusão, e o argumento pode ser usado simultaneamente com ValueFromPipeline:param(
[parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[string[]]
$Name
)
Write-Host $Name
Como você pode ver, os scripts também podem receber parâmetros através do pipeline, mas, no entanto, a aplicação prática dos atributos descritos acima é mais provável para funções avançadas , que serão discutidas abaixo.Estrutura do corpo da função
No PowerShell, uma função pode incluir três blocos opcionais de código entre colchetes de instrução - Begin, Process e End. Parece algo como isto:function test
{
param()
begin {}
process {}
end {}
}
O bloco Begin é o primeiro a ser executado uma vez e, se os parâmetros forem passados para a função pelo pipeline, o código será executado antes que o primeiro objeto chegue ao processamento. As variáveis $ _ e $ PSItem no bloco Begin nesse caso não conterão valores. Se a função for chamada usando parâmetros explicitamente especificados, eles estarão disponíveis no bloco Begin, pois não é necessário aguardar o recebimento de objetos do pipeline. Em seguida, o bloco Process é executado: se os parâmetros forem passados pelo pipeline, ele será iniciado um por um para cada objeto. No caso de parâmetros especificados explicitamente, o bloco Process inicia apenas uma vez. A função termina executando o bloco End uma vez. Obviamente, o uso dessas construções é justificado apenas se a função puder receber objetos do pipeline:function test
{
param(
[Parameter(ValueFromPipeline)]
[string[]]
$Param1,
[string]$Param2
)
begin
{
Write-Host " Begin"
Write-Host " ( pipeline):" $Param1
Write-Host " ( ):" $Param2
}
process {
Write-Host " Process"
Write-Host " ( pipeline):" $Param1
Write-Host " ( ):" $Param2
}
end
{
Write-Host " End"
Write-Host " ( pipeline):" $Param1
Write-Host " ( ):" $Param2
}
}
'um', 'dois', 'três' | teste -Param2 'quatro'
Atributo [CmdletBinding ()] e funções avançadas
Para criar funções "avançadas" (e scripts, estritamente falando), você pode usar o atributo [ CmdletBinding () ]. Em particular, permite definir funções avançadas com os recursos de cmdlets binários compilados no Visual Studio, que são classes das classes .NET Core. Como esse atributo é usado principalmente em funções, vamos parar nelas:function <Name>
{
[CmdletBinding(ConfirmImpact=<String>,
DefaultParameterSetName=<String>,
HelpURI=<URI>,
SupportsPaging=<Boolean>,
SupportsShouldProcess=<Boolean>,
PositionalBinding=<Boolean>)]
Param ()
Begin{}
Process{}
End{}
}
De fato, [CmdletBinding ()] inicializa uma nova instância da classe CmdletBindingAttribute chamando um construtor para o qual argumentos opcionais podem ser transmitidos. Sua descrição detalhada está no site da Microsoft. O atributo CmdletBinding permite controlar recursos adicionais da função avançada: adicionar suporte para -Confirm e -WhatIf (via SupportsShouldProcess), -Force, -Verbose e -Debug, além de desativar a ligação de parâmetro posicional, etc. Além disso, analisaremos o uso de parâmetros especiais.O parâmetro -Force é usado para suprimir solicitações para várias operações;-E senecessário para emular o lançamento e exibir informações sobre as consequências da execução de uma função (comando) sem esse parâmetro. Geralmente usado se uma função pode executar ações destrutivas.O item Remover C: \ Windows \ notepad.exe -WhatIf
-Confirm requer confirmação e também é usado se a função puder executar ações destrutivas.function Delete-File {
[CmdletBinding(
ConfirmImpact = 'High',
SupportsShouldProcess = $true
)]
param(
[string]$File,
[switch]$Force
)
if ($Force -or $PSCmdlet.ShouldProcess($File,"Delete file")) {
Remove-Item $File
}
}
Para processar -WhatIf e / ou -Confirm, é chamado o método ShouldProcess (SupportsShouldProcess = $ true), que solicita ou emula a execução do comando. Para implementar o processamento -Force, colocamos em primeiro lugar na condição SE. Primeiro, a expressão à esquerda do operador -ou é verificada e, se for verdadeira, o teste é interrompido - o método ShouldProcess não será chamado. Além disso, no atributo [CmdletBinding ()], especificamos o argumento ConfirmImpact, que determina o nível de influência do código no sistema e inclui o manipulador de parâmetros -Confirm. Este argumento pode assumir os seguintes valores:Nenhum ou não especificado - as mensagens de confirmação não serão exibidas, mesmo se o parâmetro -Confirm for passado.Baixa - a função afeta levemente o sistema e não cria riscos significativos de perda de dados.Média - exposição média com pouco risco de perda de dados como resultado de ações destrutivas.Alto - o código cria um alto risco de perda de dados como resultado de ações destrutivas.Por padrão, para uma sessão do PowerShell, o nível de exposição é considerado Alto. O valor atual é armazenado na variável $ ConfirmPreference e, se o código tiver o mesmo ou maior nível de impacto no sistema, uma solicitação de confirmação sempre será exibida.Opções -Verbose e -Debugnecessário para exibir informações de depuração. Seu uso é considerado um bom estilo de programação (esqueça o Write-Host, isso não é necessário em funções avançadas). O primeiro parâmetro exibe informações sobre o progresso e o segundo - informações detalhadas sobre depuração. Também possibilita alternar para a execução de código passo a passo. O comportamento de -Verbose e -Debug é definido assim:function Get-Something {
[CmdletBinding()]
param()
if ($PSBoundParameters.Verbose) {$VerbosePreference = "Continue"}
if ($PSBoundParameters.Debug) {$DebugPreference = "Continue"}
Write-Verbose "Type some verbose information"
Write-Debug "Type some debug information"
}
Para trabalhar com parâmetros especiais, usamos a variável $ PSBoundParameters. Por padrão, os valores de $ VerbosePreference e $ DebugPreference são iguais a 'SilentlyContinue'; portanto, mesmo que os parâmetros correspondentes sejam especificados, as informações de depuração não serão exibidas - elas devem ser transferidas para o estado 'Continue'.Módulos de script e criação de cmdlet
Vamos começar a criar nossos próprios cmdlets. De fato, essas são funções avançadas descritas nos chamados módulos de script - arquivos de texto com a extensão .psm1. Eles são armazenados em diretórios definidos na variável de ambiente PSModulePath. Você pode exibir os caminhos para eles usando o seguinte comando:Get-ChildItem Env: \ PSModulePath | Format-Table -AutoSizeO conjunto padrão se parece com:C: \ Users \% UserName% \ Documents \ WindowsPowerShell \ ModulesC: \ Arquivos de programas \ WindowsPowerShell \ ModulesC: \ Windows \ System32 \ WindowsPowerShell \ v1.0 \ ModulesDepois de criar o arquivo ModuleName.psm1 com a função Delete-File estendida da seção anterior, você precisa salvá-lo, por exemplo, em] C: \ Users \% UserName% \ Documents \ WindowsPowerShell \ Modules \ ModuleName. Observe que o módulo de script deve ser armazenado em um subdiretório separado, cujo nome coincide com o nome base (sem extensão) do arquivo .psm1. Depois de executar o comando Import-Module ModuleName , a função Delete-File ficará disponível para o usuário e, como é avançada, do ponto de vista prático, é o mesmo cmdlet.
Neste artigo, examinamos em detalhes a passagem de parâmetros para funções e scripts. A próxima parte da série se concentrará na programação orientada a objetos.Parte 1: Windows PowerShell Essentials2: Windows PowerShell4: ,
