Guía de Mejores Prácticas para Scripting en PowerShell

Qué es

Este artículo ofrece una guía completa sobre las mejores prácticas para scripting en PowerShell, enfocándose en la estructura del código, formato de salida, manejo de errores, optimización del rendimiento y medidas de seguridad.

Por qué

Seguir las mejores prácticas en scripting de PowerShell garantiza que tus scripts sean legibles, mantenibles, seguros y eficientes. Esto reduce la deuda técnica, mejora la colaboración y minimiza los riesgos en entornos de producción.

Cómo

Diseño de Herramientas y Controladores

Decide si estás creando una ‘Herramienta’ o un ‘Controlador’

  • Herramienta: Funciones/módulos reutilizables.
  • Controlador: Automatiza una tarea específica, no diseñado para reutilización.

Haz tu código modular

  • Utiliza funciones y módulos para maximizar la reutilización.

Usa convenciones estándar de nomenclatura

  • Sigue el formato Verbo-Sustantivo utilizando los verbos aprobados por PowerShell (Get-Verb).

Estandariza los nombres de los parámetros

  • Usa nombres como $ComputerName en lugar de prefijos personalizados.

Las herramientas deben devolver datos en bruto

  • Proporciona datos mínimamente procesados para mayor flexibilidad.

Los controladores deben devolver datos formateados

  • Formatea la salida para generar reportes fáciles de leer.

Ejemplo

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

Evita reinventar la rueda

Utiliza cmdlets integrados como Test-Connection en lugar de crear funciones personalizadas.

# Recomendado
Test-Connection $ComputerName -Quiet

Escritura de Bloques de Parámetros

Escribe siempre la ayuda

Incluye ayuda basada en comentarios con .SYNOPSIS, .DESCRIPTION y al menos un .EXAMPLE.

function Test-Help {
    <#
        .SYNOPSIS
            Demuestra documentación de ayuda adecuada.
        .EXAMPLE
            Test-Help -MandatoryParameter "Ejemplo"
            Ejecuta la función Test-Help con un parámetro obligatorio.
    #>
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [Alias("MP")]
        [String]$MandatoryParameter
    )
}

Usa [CmdletBinding()]

Activa parámetros comunes como -Verbose, -Debug, -ErrorAction.

Soporta -WhatIf y -Confirm

Para comandos que cambian el estado, usa SupportsShouldProcess.

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

Define tipos fuertes en los parámetros

Especifica siempre los tipos para validación y claridad.

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

Usa [switch] correctamente

  • Por defecto es $false.
  • Úsalo como booleano, evitando lógica de tres estados.

Formateo de Salida

Evita Write-Host salvo que sea necesario

Prefiere Write-Verbose, Write-Debug o Write-Output según corresponda.

Usa Write-Progress para mostrar avances

Write-Progress -Activity "Procesando" -Status "50% Completado" -PercentComplete 50

Usa archivos de formato para objetos personalizados

Define archivos .format.ps1xml en lugar de formateo inline.

Devuelve solo un tipo de objeto a la vez

Utiliza [OutputType()] y evita mezclar tipos de objetos.


Mejores Prácticas de Manejo de Errores

Usa -ErrorAction Stop con cmdlets

Forzar errores para manejarlos con try-catch.

try {
    Get-Item "C:\RutaInvalida" -ErrorAction Stop
} catch {
    Write-Warning "Elemento no encontrado."
}

Usa $ErrorActionPreference para operaciones fuera de cmdlets

Configúralo temporalmente a 'Stop' en operaciones críticas.

Evita usar flags y $? para manejo de errores

Prefiere bloques estructurados try-catch.

Copia $Error[0] o $_ inmediatamente dentro de catch

catch {
    $errorDetails = $_
    Write-Error "Ocurrió un error: $($errorDetails.Exception.Message)"
}

Optimización del Rendimiento

PERF-01 Mide el rendimiento cuando sea necesario

Utiliza Measure-Command para comparar métodos.

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

PERF-02 Equilibra rendimiento y legibilidad

  • Para pequeños conjuntos de datos, prioriza la legibilidad.
  • Para grandes volúmenes, considera streaming o técnicas con .NET.

Legible pero menos eficiente:

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

Optimizado para rendimiento:

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

Alto rendimiento con .NET:

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

PERF-03 Prefiere características del lenguaje sobre cmdlets

  • Construcciones del lenguaje (foreach) > Métodos .NET > Scripts > Cmdlets/Pipeline.
  • Mide siempre antes de optimizar.

Mejores Prácticas de Seguridad

Usa siempre PSCredential para credenciales

Evita contraseñas en texto plano. Utiliza parámetros [Credential()].

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

Al pasar a APIs:

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

Usa SecureString para datos sensibles

Solicita datos de forma segura y almacénalos cifrados.

$Secure = Read-Host -Prompt "Introduce datos seguros" -AsSecureString

Conversión segura a texto plano:

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

Guarda credenciales de forma segura

Utiliza Export-CliXml.

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

Guarda cadenas cifradas

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

Conclusión

Aplicando estas mejores prácticas en diseño, documentación, manejo de salida, errores, rendimiento y seguridad, podrás crear scripts de PowerShell robustos, eficientes y fáciles de mantener. Busca siempre el equilibrio entre legibilidad, rendimiento y seguridad para entregar soluciones de automatización de alta calidad.

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