Guia de Melhores Práticas para Scripting em PowerShell

O que é

Este artigo fornece um guia completo sobre as melhores práticas de scripting em PowerShell, com foco na estrutura do código, formatação de saída, tratamento de erros, otimização de desempenho e medidas de segurança.

Por que seguir

Seguir as melhores práticas no scripting em PowerShell garante que seus scripts sejam legíveis, fáceis de manter, seguros e performáticos. Isso reduz a dívida técnica, melhora a colaboração e minimiza riscos em ambientes de produção.

Como aplicar

Design de Ferramentas e Controladores

Decida se você está criando uma ‘Ferramenta’ ou um ‘Controlador’

  • Ferramenta: Funções/módulos reutilizáveis.
  • Controlador: Automatiza uma tarefa específica, não projetado para reutilização.

Torne seu código modular

  • Use funções e módulos de script para maximizar a reutilização.

Use convenções padrão de nomenclatura

  • Siga o formato Verbo-Substantivo utilizando verbos aprovados pelo PowerShell (Get-Verb).

Padronize os nomes dos parâmetros

  • Utilize nomes como $ComputerName ao invés de prefixos personalizados.

Ferramentas devem retornar dados brutos

  • Forneça dados minimamente processados para maior flexibilidade.

Controladores devem retornar dados formatados

  • Formate a saída para relatórios amigáveis ao usuário.

Exemplo

function Get-DiskInfo {
    param ([string]$ComputerName)
    Get-WmiObject Win32_LogicalDisk -ComputerName $ComputerName
}

Evite reinventar a roda

Use cmdlets nativos como Test-Connection em vez de criar funções personalizadas.

# Recomendado
Test-Connection $ComputerName -Quiet

Escrevendo Blocos de Parâmetros

Sempre escreva a ajuda

Inclua ajuda baseada em comentários com .SYNOPSIS, .DESCRIPTION e pelo menos um .EXAMPLE.

function Test-Help {
    <#
        .SYNOPSIS
            Demonstra documentação de ajuda adequada.
        .EXAMPLE
            Test-Help -MandatoryParameter "Exemplo"
            Executa a função Test-Help com um parâmetro obrigatório.
    #>
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [Alias("MP")]
        [String]$MandatoryParameter
    )
}

Use [CmdletBinding()]

Habilita parâmetros comuns como -Verbose, -Debug, -ErrorAction.

Suporte -WhatIf e -Confirm

Para comandos que alteram o estado, utilize SupportsShouldProcess.

[CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Medium")]
param ([switch]$Force)

Tipagem forte dos parâmetros

Defina sempre os tipos para validação e clareza.

param (
    [string]$Name,
    [int]$Count
)

Use [switch] corretamente

  • O padrão é $false.
  • Utilize como booleano, evitando lógica de três estados.

Formatação de Saída

Evite Write-Host quando não necessário

Prefira Write-Verbose, Write-Debug ou Write-Output conforme o contexto.

Use Write-Progress para atualizações de progresso

Write-Progress -Activity "Processando" -Status "50% Concluído" -PercentComplete 50

Use arquivos de formatação para objetos personalizados

Defina arquivos .format.ps1xml ao invés de formatação inline.

Retorne apenas um tipo de objeto por vez

Utilize [OutputType()] e evite tipos mistos.


Melhores Práticas de Tratamento de Erros

Use -ErrorAction Stop com cmdlets

Forçe erros para serem tratados com try-catch.

try {
    Get-Item "C:\CaminhoInvalido" -ErrorAction Stop
} catch {
    Write-Warning "Item não encontrado."
}

Use $ErrorActionPreference para operações não-cmdlet

Ajuste temporariamente para 'Stop' em operações arriscadas.

Evite flags e $? para tratamento de erros

Prefira blocos estruturados com try-catch.

Copie $Error[0] ou $_ imediatamente dentro do catch

catch {
    $errorDetails = $_
    Write-Error "Ocorreu um erro: $($errorDetails.Exception.Message)"
}

Otimização de Desempenho

PERF-01 Meça o desempenho quando necessário

Use Measure-Command para comparar abordagens.

Measure-Command {
    foreach ($item in $data) { Process-Item $item }
}

PERF-02 Equilibre desempenho e legibilidade

  • Para pequenos conjuntos de dados, priorize a legibilidade.
  • Para grandes volumes, considere streaming e técnicas com .NET.

Mais legível:

$content = Get-Content -Path file.txt
foreach ($line in $content) {
    Do-Something -Input $line
}

Otimizado para desempenho:

Get-Content -Path file.txt | ForEach-Object {
    Do-Something -Input $_
}

Alta performance com .NET:

$sr = New-Object System.IO.StreamReader "file.txt"
while ($sr.Peek() -ge 0) {
    $line = $sr.ReadLine()
    Do-Something -Input $line
}

PERF-03 Prefira recursos da linguagem ao invés de cmdlets

  • Construções da linguagem (foreach) > Métodos .NET > Scripts > Cmdlets/Pipeline.
  • Sempre meça antes de otimizar.

Melhores Práticas de Segurança

Sempre use PSCredential para credenciais

Evite senhas em texto simples. Use parâmetros [Credential()].

param (
    [System.Management.Automation.PSCredential]
    [System.Management.Automation.Credential()]
    $Credential
)

Ao passar para APIs:

$Insecure.SetPassword($Credential.GetNetworkCredential().Password)

Use SecureString para dados sensíveis

Solicite de forma segura e armazene criptografado.

$Secure = Read-Host -Prompt "Digite dados seguros" -AsSecureString

Converter para texto simples de forma segura:

$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Secure)
$PlainText = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)

Armazene credenciais com segurança

Use Export-CliXml.

Get-Credential | Export-CliXml -Path C:\secure\cred.xml
$Credential = Import-CliXml -Path C:\secure\cred.xml

Armazene strings criptografadas

ConvertFrom-SecureString -SecureString $Secure | Out-File -Path "${Env:AppData}\secure.bin"
$Secure = Get-Content -Path "${Env:AppData}\secure.bin" | ConvertTo-SecureString

Conclusão

Seguindo estas melhores práticas de PowerShell em design, documentação, saída, tratamento de erros, desempenho e segurança, você criará scripts robustos, eficientes e fáceis de manter. Busque sempre o equilíbrio entre legibilidade, performance e segurança para entregar soluções de automação de alta qualidade.

タイトルとURLをコピーしました