Share via


Windows PowerShell: el ciclo de vida de la avanzada función

Las funciones avanzadas de Windows PowerShell, llamadas cmdlets para scripts, pueden ser un poco confusas, pero existe una forma para dirigir sus funciones de inicialización y de limpieza.

Don Jones

Ha habido un punto de curso de confusión para un número de estudiantes en algunos de mis clases de Windows PowerShell in situ. Espero que explorar con más detalle aquí le ayudará a relajarse cierta confusión para usted. El tema es las funciones avanzadas de Windows PowerShell, conocida informalmente como cmdlets de secuencia de comandos. La plantilla para este tipo de función tiene el siguiente aspecto:

Function Do-Something { [CmdletBinding()] param( [Parameter(Mandatory=$True, ValueFromPipeline=$True)] [string[]]$computername ) BEGIN {} PROCESS {} END {} }

Hay un par de aspectos confusos para estos cmdlets. Por ejemplo, en éste, es un parámetro de entrada definido denominado - NombreDeEquipo. Esto puede aceptar la entrada de la tubería. Esto significa que puede llamar a esta función de dos maneras distintas. En primer lugar, puede tener cadenas canalizar en él, como un archivo de texto que contiene un nombre de equipo por línea:

Get-Content names.txt | Do-Something

Simplemente puede tener uno o más nombres de equipo pasan directamente al parámetro, sin utilizar la canalización a todos:

Do-Something –computername SERVER1,SERVER2

En el primer ejemplo, bloque de inicio de la función se ejecuta primero. A continuación, el bloque PROCESS se ejecuta una vez para cada nombre de canalizar en el equipo. La variable de computername $ contiene sólo un nombre de equipo a la vez. Por último, una vez que todos ellos se están procesados, el bloque final se ejecuta una vez.

En el segundo ejemplo, los bloques BEGIN y END nunca ejecutan. El bloque de proceso se ejecuta sólo una vez y $NombreDeEquipo contiene todos los nombres que se ha pasado al parámetro.

Esta diferencia de comportamiento extrema puede hacer difícil de instalación y las tareas de limpieza que se ejecutan en ambas situaciones. También puede causar confusión sobre cómo tratar con los parámetros de computername $. En el primer ejemplo sólo contiene un valor a la vez, mientras que en el segundo contendrá uno o más valores, dependiendo de lo que le ha proporcionado el parámetro – COMPUTERNAME. Puede resolver el problema de computername $ simplemente poniendo un bucle ForEach dentro del bloque de proceso:

Function Do-Something { [CmdletBinding()] param( [Parameter(Mandatory=$True, ValueFromPipeline=$True)] [string[]]$computername ) BEGIN {} PROCESS { Foreach ($computer in $computername) { # use $computer here } } END {} }

Esta técnica se garantiza que la variable de equipo $ contendrá un único nombre de equipo a la vez, por lo que es mejor trabajar con el en lugar de $NombreDeEquipo.

La instalación y limpieza es un poco más complicado. No desea realizar la configuración directamente en el bloque de proceso. Ese bloque puede ejecutar varias veces cuando se canalizan los objetos. Por otro lado, no puede poner el programa de instalación directamente en el bloque BEGIN. Que no se ejecutará si nada se canaliza en. Obviamente hay muchas maneras de que podría hacer esto, pero esto parece ser el mejor:

Function Do-Something { [CmdletBinding()] param( [Parameter(Mandatory=$True, ValueFromPipeline=$True)] [string[]]$computername ) BEGIN { $setup_done = $false function DoSomethingSetup { set-variable -name setup_done -value $true -scope 1 } DoSomethingSetup } PROCESS { if (-not $setup_done) { DoSomethingSetup } Foreach ($computer in $computername) { # use $computer here } } }

Esto aprovecha el hecho de que los bloques BEGIN, proceso y END todos comparten un ámbito común, lo que significa que comparten las mismas variables. Mediante la configuración de una variable como un indicador, puede estar seguro el contenido de la clave del bloque BEGIN: la función DoSomethingSetup: se llama sólo una vez.

Aviso de "DoSomethingSetup" función tiene que utilizar una técnica especial para establecer el indicador en $True una vez ha concluido las tareas de configuración. Dado que es una función, DoSomethingSetup tiene su propio ámbito. Normalmente no puede cambiar el valor de una variable desde fuera de ese ámbito. Puede modificar explícitamente la variable necesaria con el cmdlet Set-Variable.

Realizar el mismo truco para las tareas de limpieza es un poco más difícil. En el primer ejemplo, donde los objetos que se están canalizar en hacer algo, se ejecutará el bloque final. Sólo podría colocar allí las tareas de limpieza. Sin embargo, en el segundo ejemplo donde nada entra, final no se ejecutará nunca. El bloque de proceso se ejecutará sólo una vez, por lo que no necesariamente "sabe" que el bloque final no va a ejecutar.

No puede tener sólo el bloque PROCESS llamar a una función dentro del bloque final. Cuando se canalizan los objetos, el bloque de proceso se ejecutará varias veces, y no desea tener que llamar varias veces al bloque final.

Hay algunas formas furtivo para resolver el problema, pero el enfoque más sencillo suele ser el mejor: olvidar cuando necesita algún tipo de actividad de limpieza (tales como cerrar una conexión de base de datos), acerca de cómo utilizar los bloques BEGIN y END por completo. Que el bloque PROCESS suponga sólo se va a ejecutar una vez y sólo poner todo su instalación y limpieza ahí.

Puede ser un poco desperdicio — puede abrir y cerrar una conexión de base de datos varias veces, por ejemplo, pero es efectivo. También elimina la necesidad de tener extraños y difícil de seguir perambulations dentro del código.

Estas funciones para controlar la canalización y no canalización escenarios de programación pueden ser complicada. En algunas columnas de la próximas, mostraré algunas de las maneras que otras personas han solucionado este problema, por lo que tendrá diferentes opciones para utilizar en su propio entorno.

Denny Cherry

Don Jones es un premio MVP de Microsoft y el destinatario de "Aprender Windows PowerShell en un mes de almuerzos" (Manning publicaciones Co., 2010), un libro diseñado para ayudar a cualquier administrador serán efectivos con Windows PowerShell. Jones también ofrece formación Windows PowerShell pública y en el sitio. Póngase en contacto con él a través de su sitio Web en ConcentratedTech.com.

Contenido relacionado