Windows PowerShellConstrucciones de Windows PowerShell

Don Jones

El mes pasado les mostré algunas formas en que Windows PowerShell se podía poner en funcionamiento inmediato mediante la resolución de tareas administrativas, sin escribir realmente ningún script. Sin embargo, aunque Windows PowerShell es un shell interactivo excelente, puede aprovechar de verdad sus capacidades y automatizar más tareas complejas cuando empiece a utilizar su lenguaje de scripting eficaz y a la vez simple.

Aun así, es posible que se esté preguntando: ¿De verdad necesita Microsoft otro lenguaje de scripting? Después de todo, Microsoft nos ha traído KiXtart, un procesador de script de inicio de sesión, así como Visual Basic® Scripting Edition (VBScript). La respuesta, sin embargo, es sí. Microsoft necesita otro lenguaje de scripting. Explicaré por qué.

Era necesario que el lenguaje de Windows PowerShell™ fuera simple e intuitivo, de forma que los administradores pudieran entenderlo sin someterse a un largo periodo de aprendizaje. También era necesario que fuera muy flexible, para que pudiera acomodar toda la funcionalidad que Windows PowerShell puede proporcionar a los usuarios.

Debido a que Windows PowerShell se basa en Microsoft® .NET Framework, era necesario que su sintaxis de scripting fuera compatible con .NET. Al ensamblar un lenguaje de scripting para Windows PowerShell, los diseñadores seleccionaron una sintaxis que esencialmente es un C# simplificado (un C-Sharp destacado, uno de los lenguajes que se distribuyen con .NET Framework). ¿Por qué no seguir con una sintaxis como VBScript? En realidad, el lenguaje de scripting de Windows PowerShell no es tan distinto a VBScript, pero al ceñirse más a la sintaxis de C#, PowerShell proporciona una especie de peldaño inicial para aprender programación de .NET Framework. Si alguna vez decide cambiar a Visual Studio® y comenzar a escribir aplicaciones C#, gran parte de la sintaxis de scripting de Windows PowerShell también cambiará.

Una de las cosas más importantes en el lenguaje de scripting de Windows PowerShell, o en cualquier lenguaje de scripting, es su construcción. Existen elementos de lenguaje especiales que permiten a Windows PowerShell realizar comparaciones lógicas y llevar a cabo diferentes acciones basadas en los resultados de dichas comparaciones o que le permiten repetir una o más instrucciones.

Pensamiento lógico

Las comparaciones lógicas están en el centro de muchas construcciones de lenguaje de scripting y Windows PowerShell no es una excepción. Una comparación se centra esencialmente en dos valores u objetos y evalúa si el resultado de la comparación es True o False. Por ejemplo, podría preguntarse, "¿Es la fecha de caducidad de esta contraseña de usuario la fecha de hoy?" El resultado sería True si las fechas coinciden y False si las fechas son diferentes. Observe que estoy escribiendo en mayúsculas True y False, porque son términos que tienen un significado especial en Windows PowerShell.

A continuación, verá un ejemplo de una comparación real que podría realizar en Windows PowerShell:

PS C:\> $a = 1
PS C:\> $b = 2
PS C:\> $a -eq $b
False

he creado una variable llamada $a y la he configurado para que contenga el valor 1. En Windows PowerShell, los nombres de variables siempre comienzan con el signo de dólar, así que son fáciles de identificar. El signo = se conoce técnicamente como operador de asignación, porque se utiliza para asignar un valor. A continuación, creo una segunda variable, $b, y le asigno el valor 2. Luego viene la comparación lógica real: solicito a Windows PowerShell que compare el contenido de $a y $b mediante el operador -eq (igualdad). PowerShell realiza la comparación, determina que los dos valores no son iguales y muestra el resultado: False.

Los operadores de Windows PowerShell son algo diferentes de otros lenguajes de scripting que quizá haya visto antes y son distintos incluso de C#. La mayoría de los lenguajes utilizará el operador = para realizar comprobaciones de igualdad así como para asignar valores; Windows PowerShell evita la confusión al tener un operador dedicado para cada función. En la figura 1 se muestran los operadores de comparación de Windows PowerShell, junto con operadores equivalentes en otros lenguajes (como VBScript) que quizá ya conozca.

Figure 1 Operadores de comparación de PowerShell

Operador Nombre Descripción
-eq Igualdad Comprueba si los valores son los mismos. Otros lenguajes pueden utilizar = o == para comprobar la igualdad.
-ne No igual Comprueba la desigualdad. Otros lenguajes pueden utilizar <> o != para comprobar la desigualdad.
-gt Mayor que Comprueba si un valor es mayor que otro. Otros lenguajes pueden utilizar el carácter >.
-lt Menor que Comprueba si un valor es menor que otro. Otros lenguajes pueden utilizar el carácter <.
-ge Mayor que o igual a Comprueba si un valor es mayor que o igual a otro valor. Similar a>= en VBScript y otros idiomas.
-le Menor que o igual a Comprueba si un valor es menor que o igual a otro valor. Similar a<= en VBScript y otros idiomas.

Estos operadores de comparación tienen otra función de interés. Examine esta comparación:

PS C:\> $a = "TechNet"
PS C:\> $b = "technet"
PS C:\> $a -eq $b
True

de forma predeterminada, los operadores de comparación no distinguen entre mayúsculas y minúsculas, lo que significa que la versión escrita en mayúsculas de TechNet se toma como equivalente de "technet". Esto es conveniente porque en la mayoría de las tareas administrativas no se tiene en cuenta si las letras se escriben en mayúsculas o no. Sin embargo, a veces es posible que solicite a Windows PowerShell que realice una comparación distinguiendo entre mayúsculas y minúsculas mediante la anteposición de c en el operador de comparación:

PS C:\> $a -ceq $b
False

Del mismo modo, si alguna vez le preocupa o le desconcierta si Windows PowerShell va a realizar o no una comparación en la que no tenga en cuenta mayúsculas y minúsculas, puede forzarlo a hacerlo mediante la anteposición de la letra i:

PS C:\> $a -ieq $b
True

Simplemente recuerde que las comparaciones lógicas siempre dan como resultado uno de los dos siguientes valores: True o False.

Toma de decisiones

Ahora que sabe cómo escribir comparaciones lógicas, puede comenzar a utilizarlas en construcciones. La primera construcción que le mostraré permite a Windows PowerShell tomar decisiones basadas en una comparación. Se denomina construcción If y existen algunas variaciones de la misma. La más simple es la siguiente:

PS C:\> if ($a -eq $b) {
>> Write-Host "They are equal"
>> }
>>
They are equal

Existen algunos aspectos interesantes que comentar aquí. En primer lugar, las variables $a y $b todavía contienen los valores "TechNet" y "technet", respectivamente. Comencé la construcción con la palabra clave If. A continuación, entre paréntesis, especifiqué la comparación lógica que quería realizar. Después nos encontramos con una llave, que indica el comienzo de lo que llamaré código condicional, el código que Windows PowerShell ejecutará si la comparación devuelve un resultado True. Como sabrá por el ejemplo anterior, esta comparación devuelve el resultado True, por lo que espero que el código condicional se ejecute. Escribo el código condicional, Write-Host "They are equal" y presiono Entrar. Por último, finalizo la sección del código condicional escribiendo una llave de cierre y presionando Entrar dos veces. La segunda vez que presiono Entrar, lo hago sobre una línea en blanco que permite al analizador saber que he terminado de escribir y que estoy listo para que se ejecute el código.

Observe que esta construcción no se está ejecutando desde un archivo de script. Simplemente la escribí en la línea de comandos de Windows PowerShell. Lo que hace que Windows PowerShell sea exclusivo en el mundo del scripting de Windows es que los scripts se pueden crear de forma interactiva, así como almacenarse en un archivo permanentemente.

En cuanto escribí la llave de apertura y presioné Entrar, Windows PowerShell mostró un símbolo de >>. Esa es su forma de decir, "reconozco que se encuentra en una construcción, estoy listo para que empiece a escribir lo que vaya en la construcción". Tras escribir la llave de cierre y presionar Entrar dos veces, Windows PowerShell ejecutó la construcción de forma inmediata, determinó que la comparación lógica era True y ejecutó el código condicional. Esto puede comprobarse porque "They are equal" se mostró antes de que PowerShell volviera a su símbolo normal. El uso de Windows PowerShell para crear scripts de forma interactiva permite probar pequeños fragmentos de código antes de ensamblarlos en un script de carácter más permanente, lo que hace que el aprendizaje y la depuración sean más sencillos.

Debo señalar que Windows PowerShell no es muy quisquilloso con cosas como presionar Entrar. Por ejemplo, esto es prácticamente lo mismo que el ejemplo anterior:

PS C:\> if ($a -eq $b) { Write-Host "They are equal" }
They are equal

Debido a que escribí todo esto en una sola línea, Windows PowerShell no necesitó mostrar el símbolo especial de >>; simplemente ejecutó la construcción cuando presioné Entrar al final de la línea. ¿Cómo supo Windows PowerShell que podía ejecutar la construcción? Porque estaba completa en el momento que escribí la llave de cierre.

Aludí a otras variaciones de la construcción If. A continuación se muestra un ejemplo completo, presentado como puede aparecer en un archivo de scripts PS1, en lugar de en shell:

if ($a -eq $b) {
  Write-Host "They are equal"
} elseif ($a -lt $b) {
  Write Host "One is less than the other"
} else {
  Write Host "One is greater than the other"
}

La construcción comienza del mismo modo, con la palabra clave If. Sin embargo, en el supuesto caso de que la comparación sea False, he proporcionado otra comparación con la palabra clave Elseif. Si esta última comparación también es False, mi última palabra clave, Else, proporciona un conjunto final de código que se ejecutará.

Repetición

Windows PowerShell incluye un par de construcciones para ejecutar código una y otra vez, hasta que la comparación sea True o False. Los programadores denominan a este fenómeno construcciones de bucle. Y lo que es mejor, una de las construcciones de bucle más útiles es capaz de enumerar los objetos de una colección y ejecutar una o varias líneas de código para cada objeto. De manera apropiada, la construcción recibe el nombre de construcción foreach y se presenta del siguiente modo:

PS C:\> $names = get-content "c:\computers.txt"
PS C:\> foreach ($name in $names) {
>> Write-Host $name
>> }
>>
don-pc
testbed

Comencé a pedirle al cmdlet Get-Content de Windows PowerShell que recuperara el contenido del archivo c:\computers.txt, un archivo que creé y que contenía un nombre de equipo por línea. Windows PowerShell trata cada línea como un objeto, por lo que el archivo es fundamentalmente una colección que contiene dichos objetos. La colección concluye en la variable $names. Mediante la palabra clave Foreach, le indico a Windows PowerShell que enumere la colección $names, haciendo uso de la variable $name para representar el objeto actual cada vez que se ejecute el bucle. El código de bucle debe ir entre llaves. Así que, para cada nombre del archivo, introduciré el nombre en la línea de comandos. Y, como se puede ver en el resultado que sigue a la construcción, esto es exactamente lo que hace Windows PowerShell. A continuación, puede comprobar el modo en el que esto proporcionaría una ventaja obvia en los scripts administrativos: por ejemplo, puede construir fácilmente una lista de nombres de servidores y pedir a Windows PowerShell que recupere, a su vez, información de cada uno de ellos.

Construcciones reales

Tomemos las comparaciones lógicas, la construcción If y la construcción foreach y hagamos algo útil. Me gustaría comprobar rápidamente el estado del servicio Messenger de un conjunto de servidores. Espero que el servicio se detenga en la mayoría de los servidores, por lo que no deseo que Windows PowerShell muestre todos los servidores en los que el servicio se encuentra en el estado que espero; sólo quiero que muestre los servidores en los que ya se ha iniciado el servicio Messenger porque éstos son los servidores con los que necesito trabajar.

El cmdlet Get-Service de Windows PowerShell puede ayudarme a recuperar la información que necesito para el equipo local. Sin embargo, desafortunadamente, no puede extenderse hasta un equipo remoto, que es en realidad mi objetivo. Por suerte, también puedo tener acceso a la misma información a través de Instrumental de administración de Windows (WMI), haciendo uso del cmdlet Get-WMIObject, que me permite trabajar con un equipo remoto. El script es el siguiente:

$names = get-content c:\computers.txt
foreach ($name in $names) {
  $svc = get-wmiobject win32_service '
   -computer $name -filter "name='messenger'"
  if ($svc.started -eq $True ) {
    write-host "$name has Messenger running"
  }
}

¿Ha observado el carácter ' de la tercera línea? Indica a Windows PowerShell que la siguiente línea es una continuación. Es útil en casos como éste, en los que no encajaría toda la línea en la revista sin ajustarlo. Observe también que la construcción If compara $svc.started con $True. La variable $True es una variable especial de Windows PowerShell que representa el valor booleano True. La variable complementaria, $False, representa el valor booleano False. En realidad, podría haber hecho un pequeño acceso directo:

$names = get-content c:\computers.txt
foreach ($name in $names) {
  $svc = get-wmiobject win32_service '
   -computer $name -filter "name='messenger'"
  if ($svc.started) {
    write-host "$name has Messenger running"
  }
}

Recuerde que la condición de la construcción If sólo necesita ser True o False. Normalmente, se obtiene True o False al comparar dos valores, como hice en la primera versión de este script. Sin embargo, debido a que la propiedad Started es True o False, no es necesario compararla con True o False.

Una herramienta útil

Aquí tiene una herramienta administrativa sencilla y útil que utilizan las construcciones para realizar su trabajo. Independientemente de si la escribe en Windows PowerShell de forma interactiva o la guarda en un archivo PS1 para volverla a utilizar de forma sencilla, se trata de una herramienta práctica para comprobar el estado de un servicio en varios equipos, así como de una gran demostración de cómo las construcciones pueden ayudar a automatizar tareas administrativas.

Don Jones es el director de proyectos y servicios de SAPIEN Technologies y coautor de Windows PowerShell: TFM (SAPIEN Press, 2006). Póngase en contacto con Don a través de su sitio Web en ScriptingAnswers.com (en inglés)

© 2008 Microsoft Corporation and CMP Media, LLC. Reservados todos los derechos; queda prohibida la reproducción parcial o total sin previa autorización.