Funciones de PowerShell

Esta entrada es la parte 12 de 13 en la serie Aprender PowerShell

En este episodio de la serie Aprender PowerShell examinaremos las funciones de PowerShell. En el último episodio cubrimos los scripts de PowerShell donde comenzamos a crear soluciones y resolver problemas usando PowerShell. Los scripts de PowerShell son geniales y mucha gente pasa bastante tiempo en esta etapa cuando aprende PowerShell. Los scripts te permiten mantener las cosas bastante simples, y pueden ayudarte a automatizar tareas rápidamente. ¡A medida que vayas mejorando y empieces a escribir más PowerShell vas a tener que buscar la creación de funciones PowerShell!

Vídeo

Si prefieres el formato de vídeo en lugar de la documentación escrita, hablo de este tema en el siguiente vídeo de TechThoughts:

Cuándo debes escribir una función de PowerShell

Al fin y al cabo un script de PowerShell es un conjunto de código que realiza una tarea. ¡Eso es lo que hace una función PowerShell también! Entonces, ¿por qué elegirías escribir una función frente a un script? Vamos a profundizar en algunas razones a continuación. Sin embargo, en términos generales, un script es algo para ti. Cuando quieras empezar a compartir tu código, o hacer que tus compañeros de equipo lo utilicen, querrás empezar a utilizar algunas de las capacidades que proporcionan las funciones. No hay una línea firme. Para una tarea rápida que se ejecutará en tu estación de trabajo una sola vez, un script podría tener sentido. Si está escribiendo algo de PowerShell que otros podrían utilizar, o que podría utilizar más de una vez, una función probablemente servirá mejor.

  • Un solo propósito – una función se utiliza normalmente para realizar una tarea estrecha y «hacer una cosa, y hacerlo bien». Esto hace que las funciones sean altamente reutilizables. Si escribe una función de registro, por ejemplo, puede utilizar esa función de registro de PowerShell con otras funciones o scripts.
  • Ayuda – las funciones admiten comentarios basados en la ayuda. Esto permite a tus usuarios hacer cosas como escribir Get-Help y averiguar cómo usar tu función.
  • Parámetros – el soporte para declaraciones y control de parámetros simples y avanzados permite que tu función sea dinámica y tome varias formas de entrada del usuario.
  • Testable – las funciones pueden ser probadas y burladas lo que mejora enormemente la calidad del código.

Anatomía de una función PowerShell

Aquí está el diseño básico y el orden de una función PowerShell. A continuación nos sumergiremos en cada una de estas secciones y las exploraremos en detalle.

# function help - (optional but strongly encouraged)# function name# CmdletBinding - (optional)# parameters - (optional)# function logic (optional Begin / Process / End)# return - (optional)function Verb-Noun { param ( ) begin { } process { } end { }}

Ayuda de la función

Cuando incluyas la ayuda en la parte superior de tu función se mostrará cuando se ejecute Get-Help contra tu función. Esta es una poderosa capacidad cuando otros están explorando su código. Tomarse el tiempo para dar cuerpo a una buena Sinopsis y Descripción combinada con ejemplos sólidos ayudará a otros a entender para qué sirve su función y cómo usarla.

Todos los campos de ayuda son opcionales y puede añadirlos o quitarlos a su gusto. Te recomiendo que incluyas al menos los campos de abajo como mínimo.

<#.SYNOPSIS Short description.DESCRIPTION Long description.EXAMPLE C:\PS> Example of how to use this cmdlet.EXAMPLE C:\PS> Another example of how to use this cmdlet.PARAMETER InputObject Specifies the object to be processed. You can also pipe the objects to this command..OUTPUTS Output from this cmdlet (if any).NOTES General notes.COMPONENT The component this cmdlet belongs to#>

CmdletBinding


Cuando escribes una gran función y le das un nombre como Get-AllFileInformation, parece y actuará como un cmdlet. Pero es una distinción importante que una función de PowerShell no es un cmdlet. Los cmdlets están escritos y compilados en C# y tu función PowerShell está escrita en PowerShell.

CmdletBinding es un atributo de las funciones que habilita capacidades que las hacen operar más como cmdlets compilados. Añadir esto a la parte superior de su función le dará a su función un montón de capacidades adicionales como:

  • Write-Verbose – permite a los usuarios utilizar el interruptor -Verbose para ver lo que su función está haciendo mientras lo hace.
  • ShouldProcess – si su función va a hacer un cambio en un sistema que es de alto riesgo, es posible que desee que el usuario confirme la acción.
  • PositionalBinding – permite que su función se ejecute sin proporcionar explícitamente el nombre de cada parámetro. Los valores pueden ser inferidos por el orden en que se proporcionan a su función

parámetros

param ( $City, $Units = 'USCS', $Language = 'en', $Short)

Los parámetros sirven para proporcionar al usuario una forma de interactuar dinámicamente con su función. Usted puede tomar en varias formas de entrada y realizar una amplia variedad de controles y validaciones para asegurarse de que está recibiendo el tipo de información correcta.

Usted puede permanecer muy básico y sólo declarar los nombres de sus parámetros. Alternativamente, puede ser muy específico en lo que se requiere para sus parámetros:

  • Si el parámetro es obligatorio
  • La posición de un parámetro (el orden)
  • El tipo de parámetro (string/int/bool/etc)
  • Establecer valores por defecto
  • Validación de entradas
  • Conjuntos de parámetros
  • Mucho más
  • Este post no puede cubrir todas las posibles configuraciones de parámetros. Incluso después de años de escribir PowerShell me resulta difícil memorizar toda la configuración de parámetros y la sintaxis. Saber que las declaraciones de parámetros son su manera de tomar la entrada en su función. Usted puede proporcionar una gran cantidad de detalles y controles a ellos, o simplemente mantenerlos simples dependiendo de sus necesidades. Marca los enlaces de parámetros en la parte inferior de este post. Incluso hoy en día, los visito con frecuencia!

    Comienzo Proceso Fin

    Estas tres palabras clave son fases que puedes declarar dentro de tu función.

    • Comenzar inicializará algunos pasos al comienzo
    • Proceso procesará cada objeto tal y como se recibe
    • Fin puede realizar la limpieza.

    Esto es especialmente útil si quieres que tu función soporte el procesamiento de entradas del pipeline.

    Esto puede ser difícil de entender en teoría, así que aquí hay un ejemplo que demuestra su uso.

    function Get-PipelineBeginEnd { param ( $SomeInput ) begin { "Begin: The input is $SomeInput" } process { "The value is: $_" } end { "End: The input is $SomeInput" }}#Get-PipelineBeginEnd1, 2, 3 | Get-PipelineBeginEnd -SomeInput 'Test'

    Cuando ejecutes el código anterior observa que Begin se ejecuta una vez, al igual que End. Process se ejecuta para cada elemento que se le pasa y Process tiene acceso al objeto actual en el pipeline.

    Lógica de la función

    La lógica contenida dentro de una función PowerShell no es diferente a la de un script. Aquí es donde escribirá la lógica central que realiza la tarea para la que su función está destinada. Esto fue cubierto en los episodios 1-10 de este curso. También puedes ver un ejemplo completo en vivo en el episodio Scripts de PowerShell.

    Retorno de función

    No todas las funciones devuelven algo cuando se ejecutan. Si tu función va a devolver algo puedes usar opcionalmente return. Ten en cuenta que al usar return, todas las acciones posteriores de la función se detendrán y la función terminará.

    function Get-Total { param ( $Number1, $Number2 ) $total = $Number1 + $Number2 return $total}Get-Total -Number1 2 -Number2 2

    En el ejemplo anterior esta sencilla función contiene dos parámetros de tipo entero. La lógica de la función suma los dos números y devuelve el entero al usuario.

    Tu primera función PowerShell

    Echa un vistazo a la función PowerShell de abajo. Observe que el diseño se adhiere a lo que hemos cubierto previamente. También note que la sección de ayuda proporciona una gran cantidad de detalles en cuanto al propósito y el uso de la función.

    <#.SYNOPSIS Returns your public IP address..DESCRIPTION Queries the ipify Public IP Address API and returns your public IP..EXAMPLE Get-PublicIP Returns the public IP..OUTPUTS System.String.NOTES https://github.com/rdegges/ipify-api#>function Get-PublicIP { $uri = 'https://api.ipify.org' try { $invokeRestMethodSplat = @{ Uri = $uri ErrorAction = 'Stop' } $publicIP = Invoke-RestMethod @invokeRestMethodSplat } catch { Write-Error $_ } return $publicIP}#Get-PublicIP

    Como la lógica real de esta función es bastante simple, podría ser tentador dejarlo como un script. Tenga en cuenta sin embargo que esto hace una cosa específica, y lo hace bien. Ahora podría incorporar esta función en otra lógica avanzada, en lugar de tener que referenciar o importar un script. Otros usuarios en su entorno también podrían empezar a utilizar esta función una vez que se familiaricen con ella.

    Alcance de la función

    Como la mayoría de los lenguajes PowerShell tiene reglas de alcance para las variables. Cuando una variable está dentro de una función ya no podrás «ver» su valor. Aquí hay un ejemplo de este comportamiento:

    function Get-NumberTimesTwo { param ( $Number ) $total = $Number * 2 return $total}#Get-NumberTimesTwoGet-NumberTimesTwo -Number 2

    La función se comporta como se espera y multiplicará correctamente un número por dos. Sin embargo, en tu consola intenta ver cuál es el valor de $total. No podrás hacerlo. Esto se debe a que $total tiene un alcance en la función, y no en su sesión de consola activa.

    Esto puede ser confuso para la gente nueva en PowerShell y puede hacer que escribir funciones sea más difícil. Hay un par de estrategias para lidiar con esto.

    Podría escribir la mayor parte de su lógica en un formato de tipo script, probando las variables a medida que avanza. Una vez que esté seguro de que la lógica está funcionando como se pretende, entonces podría envolver la lógica dentro de una función.

    Alternativamente, puede utilizar Write-Host, Write-Output, o mejor aún Write-Debug para ver lo que está pasando con sus variables dentro de su función!

    function Get-NumberTimesTwo { param ( $Number ) $total = $Number * 2 Write-Debug $total return $total}#Get-NumberTimesTwoGet-NumberTimesTwo -Number 2 -Debug

    Note que con el interruptor de depuración tenemos acceso al valor dentro de $total para asegurar que nuestra lógica está haciendo lo que pretendemos.

    Ejemplo de cierre

    Aquí tienes un ejemplo de cierre más amplio de dos Funciones PowerShell que te permitirán navegar por la popular web reddit usando PowerShell!

    Visita el enlace gist de GitHub de abajo para acceder al código y cargarlo en tu consola.

    https://gist.github.com/techthoughts2/cd2b720c9b291510cbd643e6ca73e05f

    Mientras exploras estas funciones intenta responder a las siguientes preguntas:

    • De las dos funciones, ¿cuál es la función principal?
    • ¿Son funciones estándar o avanzadas?
    • ¿Cuál de las funciones va a soportar la entrada de pipeline?

    Additional Reading

    • Functions
    • Parameters
    • Functions Advanced
    • Functions Advanced Parameters
    • PowerShell Approved Verbs
    • CmdletBindingAttribute

    Series Navigation << PowerShell ScriptsManage Cloud with PowerShell >>