Windows PowerShellEl poder de las variables

Don Jones

Si trabaja con un lenguaje de secuencias de comandos basado en Windows, como VBScript o KiXtart, estará acostumbrado a variables que no son más que un tipo de mecanismo de almacenamiento de datos. También Windows PowerShell tiene variables, pero son mucho más eficaces que las variables de los lenguajes de secuencias de comandos antiguos. Las variables de Windows

PowerShell se asignan realmente a clases subyacentes en Microsoft ® .NET Framework. Y, en Framework, las variables son objetos, lo que significa que pueden almacenar datos y también manipularlos de muchas maneras. De hecho, las sólidas capacidades de las variables de Windows PowerShell™ son la razón de que el lenguaje de secuencias de comandos de Windows PowerShell no contenga funciones intrínsecas de manipulación de los datos. Estas funciones no son necesarias, dado que las propias variables ya proporcionan la funcionalidad.

Declaración de variables

Aunque el cmdlet New-Variable de Windows PowerShell permite declarar una variable y asignarle un valor inicial, no tiene que usar el cmdlet. En su lugar, puede crear una variable nueva directamente asignándole simplemente un valor:

$var = "Hello"

en Windows PowerShell, los nombres de variable siempre comienzan con un símbolo de dólar ($) y pueden contener una combinación de letras, números, símbolos o incluso espacios (aunque si usa espacios, necesitará poner la variable entre corchetes, por ejemplo, ${My Variable} = "Hello"). En este ejemplo, se ha creado una nueva variable denominada $var y se le ha asignado el valor inicial de "Hello". Como en este caso el valor es una cadena de caracteres, Windows PowerShell usará el tipo de dato String para almacenar el valor. En .NET Framework, esta es la clase System.String, que probablemente tenga integrada mayor funcionalidad que ningún otro tipo de variable. Por ejemplo, si deseo ver una versión en minúsculas del valor en $var, puedo hacer esto:

PS C:\> $var.ToLower()
hello
PS C:\>

El método ToLower está integrado en la clase System.String, y produce una representación en minúsculas del valor de la cadena. Si bien, no cambia el contenido real de la variable $var. Para ver una lista completa de todo lo que es capaz de hacer la clase System.String, canalice una variable de cadena al cmdlet Get-Member, por ejemplo:

$var | get-member

En la figura 1 se muestra el resultado, que incluye un par de docenas de métodos usados para manipular cadenas. Casi toda la funcionalidad proporcionada por las funciones de manipulación de cadenas de VBScript la proporcionan los métodos de la variable de cadena de Windows PowerShell.

Figura 1 El resultado de la clase System.String

Figura 1** El resultado de la clase System.String **(Hacer clic en la imagen para ampliarla)

Muchas de las capacidades de la variable de cadena son más útiles en un contexto administrativo que las funciones de cadena en un lenguaje como VBScript. Suponga que ha escrito una secuencia de comandos que lee las rutas de Convención de nomenclatura universal (UNC) desde un archivo y hace algo con ellas. Desearía comprobar que cada ruta leída es una ruta UNC antes de intentar usarla. El método StartsWith le permite confirmar que un valor de cadena comienza con los caracteres de barra diagonal inversa necesarios que requiere una ruta UNC:

PS C:\> $path = "\\Server\Share"
PS C:\> $path.StartsWith("\\")
True
PS C:\>

Como StartsWith devuelve un valor True o False, puede usarlo en construcciones lógicas:

if ($path.StartsWith("\\")) {
 # code goes here
}

Windows PowerShell proporciona incluso un formulario de finalización automática para métodos de variables, lo que reduce la necesidad de escribir por su parte. Si $var contiene una cadena, puede escribir

$var. 

y, a continuación, presionar Tab, lo que muestra el nombre del primer método para la variable $var. Al presionar de nuevo Tab se pasa al siguiente método y, al presionar Mayús+Tab, se vuelve al método anterior. De este modo, puede recorrer todos los métodos de variable disponibles hasta encontrar el deseado.

Confusión de variables

Hasta ahora, mis ejemplos han permitido a Windows PowerShell determinar el tipo de datos de mis variables. El hecho de asignar una cadena a una variable obliga básicamente a la variable a ser de la clase System.String. Por otra parte, el hecho de asignar un número a una variable tiene como resultado generalmente el que la variable se convierta en un entero (o, más específicamente, un Int32, que puede almacenar un intervalo específico de valores). Considere, por ejemplo, este caso:

PS C:\> $int = 5
PS C:\> $int | get-member

  TypeName: System.Int32

Este resultado truncado muestra que Windows PowerShell trata $int como un Int32, que tiene su propio conjunto de métodos y propiedades. Y, de hecho, presenta menos métodos y propiedades que el tipo String.

$int se convirtió en un Int32 porque el valor no estaba incluido entre comillas y porque únicamente estaba formado por dígitos. Si hubiera estado entre comillas, se habría interpretado como un System.String.

Al dejar que Windows PowerShell decida el tipo de datos que se va a usar, no siempre se obtiene el resultado deseado. Suponga que lee valores de un archivo y desea que los valores se traten siempre como cadenas. Algunos de los valores, sin embargo, quizás sólo contengan dígitos, lo que aumenta la posibilidad de que Windows PowerShell los trate como Int32 u otro tipo numérico. Esto puede causar problemas para la secuencia de comandos. Si Windows PowerShell no reconoce el valor como una cadena, entonces todos los métodos de la clase System.String no están disponibles (y la secuencia de comandos podría depender de uno de estos métodos no disponibles).

Una solución provisional podría ser obligar a Windows PowerShell a tratar una variable como un tipo determinado al declarar dicho tipo la primera vez que use la variable. Por ejemplo:

[string]$var = 5

normalmente, $var habría sido un Int32, pero aquí he obligado a Windows PowerShell a crear $var como String, lo que garantiza que pueda usar todos los métodos asociados con la clase System.String. La declaración del tipo de variable también proporciona una práctica clase de autodocumentación para el código, dado que ahora es obvio el tipo de datos que se espera que entre en $var. De hecho, me he acostumbrado a declarar siempre un tipo específico para todas mis variables, y a dejar a Windows PowerShell completamente al margen de la decisión. De esta manera, el comportamiento de mis secuencias de comandos es más previsible y, en varios casos, me ha ahorrado bastante tiempo de depuración.

Como cabría esperar, declarar las variables por la fuerza tiene repercusiones, aunque no son necesariamente malas. Tome este ejemplo, en el que no se declara el tipo de la variable:

PS C:\> $me = 5
PS C:\> $me = "Don"

La variable $me era inicialmente un Int32, pero Windows PowerShell la cambió a un String al agregar el valor "Don". Windows PowerShell puede cambiar el tipo de una variable según sea necesario, siempre que la variable no se haya establecido ya en un tipo específico.

En este ejemplo, he obligado a $me a ser un Int32 mediante el nombre de tipo [int]:

PS C:\> [int]$me = 5
PS C:\> $me = "Don"
Cannot convert value "Don" to type 
"System.Int32". Error: "Input string 
was not in a correct format."
At line:1 char:4
+ $me <<<< = "Don"

Luego, cuando he intentado asignarle un valor de cadena, se ha mostrado un mensaje de error. Dado que había obligado explícitamente a $me a ser un Int32, Windows PowerShell esperaba convertir la cadena "Don" en un valor entero. Pero no fue posible, ni tampoco lo fue cambiar el tipo de $me a String.

Hay tantos tipos...

Hay muchos tipos disponibles en Windows PowerShell. De hecho, puede usar cualquier tipo .NET Framework (y hay cientos de tipos disponibles). Sin embargo, Windows PowerShell define varios accesos directos para tipos de datos comunes. La figura 2 es sólo una lista parcial, que muestra 10 de los accesos directos de tipo de uso más común. Para ver una lista completa, consulte la documentación de Windows PowerShell.

Figure 2 Accesos directos comunes de tipo

Acceso directo Tipo de datos
[datetime] Fecha u hora
[string] Cadena de caracteres
[char] Carácter único
[double] Número flotante de precisión doble
[single] Número flotante de precisión simple
[int] Entero de 32 bits
[wmi] Instancia o recopilación de Instrumental de administración de Windows (WMI)
[adsi] Objeto de Servicios de Active Directory
[wmiclass] Clase WMI
[Boolean] Valor True o False

También puede declarar un tipo de variable con el nombre completo de la clase .NET Framework, de esta forma:

[System.Int32]$int = 5

Esta técnica permite usar tipos que están en .NET Framework, pero que no tienen acceso directo específico en Windows PowerShell.

Extensión de tipos

Quizás lo mejor de Windows PowerShell sea su capacidad para ampliar las capacidades de estos tipos de variables. En la carpeta de instalación de Windows PowerShell (normalmente en %systemroot\system32\windowspowershell\v1.0, aunque encontrará que la ruta de acceso es algo diferente en sistemas de 64 bits), encontrará un archivo llamado types.ps1xml. Este archivo se puede editar en Bloc de notas o en un editor XML, como PrimalScript. De forma predeterminada, la clase System.String no se incluye en la lista, aunque muchos otros tipos sí. Sin embargo, puedo agregar una nueva capacidad al tipo System.String si lo agrego al archivo types.ps1xml.

Después de realizar el cambio, debo cerrar y volver a abrir Windows PowerShell. También necesito asegurarme de que la directiva local de ejecución de secuencia de comandos admite la ejecución de secuencias de comandos sin firmar, dado que no he firmado types.ps1xml:

Set-executionpolicy remotesigned

Ahora, una vez que reinicio Windows PowerShell, puedo usar la nueva funcionalidad, de esta forma:

PS C:\> [string]$comp = "localhost"
PS C:\> $comp.canping
True
PS C:\>

Como puede ver, he agregado una propiedad CanPing a la clase System.String. Esto devuelve True o False para indicar si el equipo local puede hacer ping de la dirección contenida en la cadena. En la figura 3, advertirá que la consulta WMI usa una variable especial, $this. La variable $this representa el valor actual contenido en la cadena y el paso del contenido de la variable de cadena a la consulta WMI.

Figure 3 Extensión del tipo System.String

<Type>
  <Name>System.String</Name>
  <Members>
    <ScriptProperty>
      <Name>CanPing</Name>
      <GetScriptBlock>
      $wmi = get-wmiobject -query "SELECT *
FROM Win32_PingStatus WHERE Address = '$this'"
      if ($wmi.StatusCode -eq 0) {
        $true
      } else {
        $false
      }
      </GetScriptBlock>
    </ScriptProperty>
  </Members>
</Type>

Dejemos que una variable haga el trabajo.

Windows PowerShell proporciona tipos de variables flexibles y con abundantes características, junto con un sistema igualmente flexible para ampliar la funcionalidad de los tipos. Estas capacidades facilitan la creación de secuencias de comandos muy eficaces. De hecho, en secuencias de comandos complejas, las variables pueden convertirse en un bloque de creación fundamental y, en muchos casos, adoptar las capacidades avanzadas que encontraría normalmente en una función más compleja.

Obtenga más información en línea.

Acompáñeme en esta serie de webcasts, celebradas el segundo martes de cada mes, donde continuaremos zambulléndonos en la rica funcionalidad de secuencia de comandos que ofrece Windows PowerShell. Visite microsoft.com/events/series/donjonesscripting.mspx (en inglés) para registrarse ya mismo.

20 de febrero de 2007 Windows PowerShell: curso básico de secuencias de comandos

Participe en esta webcast para obtener más información acerca de las variables, construcciones de lenguaje, secuencias de comandos y funciones de Windows PowerShell. En este curso de una hora, demostraremos cómo el lenguaje de secuencias de comandos de Windows PowerShell, sencillo pero efectivo, acelera la automatización administrativa de Windows ®. Exploramos también varias herramientas de terceros que facilitan en gran medida el uso de las secuencias de comandos de Windows PowerShell.

20 de marzo de 2007 Windows PowerShell: funciones, filtros y eficacia

Aprenda a crear código efectivo y modularizado en funciones y filtros de Windows PowerShell. Exploramos las eficaces reglas de ámbito de Windows PowerShell que permiten encapsular completamente funciones y filtros, y explican cómo puede volver a emplear fácilmente estos filtros y funciones en los proyectos. Demostramos también cómo puede agregar sus propias funciones personalizadas al ámbito global de Windows PowerShell, lo que facilita el ensamblado de una biblioteca de funciones útiles al alcance de su mano.

17 de abril de 2007 Windows PowerShell y el Instrumental de administración de Windows (WMI)

Windows PowerShell puede aprovechar la eficacia y la capacidad de WMI. Describimos no sólo cómo usar Windows PowerShell para tener acceso a WMI, sino también cómo transmitir objetos y recopilaciones de WMI por la canalización de Windows PowerShell. Exploramos cómo usar las propiedades y los métodos de WMI en secuencias de comandos de Windows PowerShell e ilustramos las características de seguridad y configuración subyacentes de WMI.

22 de mayo de 2007 Windows PowerShell: conversión desde VBScript

¿Desea convertir sus secuencias de comandos, o simplemente sus conocimientos, de VBScript a Windows PowerShell? Participe en esta webcast para conocer cómo. Exploramos cómo Windows PowerShell incluye todas las construcciones y las características principales de VBScript, lo que facilita la aplicación de sus conocimientos de VBScript a este nuevo entorno administrativo. Ilustramos la conversión de herramientas de VBScript al lenguaje de secuencias de comandos nativo en Windows PowerShell. Examinamos también la estructura única de Windows PowerShell y mostramos cómo empezar a usar el lenguaje de secuencias de comandos de Windows PowerShell de forma que sus esfuerzos sean más efectivos.

19 de junio de 2007 Windows PowerShell: extensiones ocultas

En esta webcast, exploramos cómo Windows PowerShell usa la eficacia y flexibilidad de .NET Framework para ocuparse de los datos, y proporciona centenares de funciones integradas para administrar cadenas, fechas y otros tipos de datos. Pero, ¿sabía que puede ampliar estas funciones mediante secuencias de comandos de Windows PowerShell? Aquí mostramos cómo crear variables de cadena que contienen no sólo un nombre de equipo, sino que, además, pueden indicar si el equipo está en funcionamiento. Aprenda a crear variables de fecha y hora que pueden dar formato automáticamente a sus datos sin el uso de funciones externas. Participe en esta sesión para aprender a crear todo tipo de nuevas funciones en Windows PowerShell en tan sólo unos minutos, y acelerar y facilitar la administración de Windows.

Don Jones es director de proyectos y servicios de SAPIEN Technologies y coautor de Windows PowerShell: TFM (SAPIEN Press). Póngase en contacto con Don en www.ScriptingAnswers.com.

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