Hey, Scripting Guy!Subidón de adrenalina

Los Scripting Guys de Microsoft

No cabe duda alguna de que escribir en TechNet Magazine es el trabajo más importante y gratificante que nadie pueda tener en el mundo. Por supuesto, sería aún mejor si nos pagaran por ello, pero eso es otra historia. ¿Cómo de prestigioso es este trabajo? Digámoslo así: en estos momentos, a lo largo y ancho del mundo, hay miles de niños que, antes de dormir, miran a sus madres y les confiesan: "Mami, cuando sea mayor, quiero escribir una columna mensual de scripting en TechNet Magazine".

Nota Bueno, también hay gente de todo el mundo que cree que la columna realmente la escriben niños. Pero, de nuevo, eso es otra historia.

Ya se sabe que a los Scripting Guys nos encanta recibir más y más halagos, fruto de nuestro trabajo para TechNet Magazine; hasta hemos aprendido a convivir con paparazzis y cazadores de autógrafos. Pero lo cierto es que no hacemos este trabajo por la fama y la gloria; lo hacemos porque nos gusta sentir el subidón de adrenalina que implica escribir scripts de administración de sistemas.

De acuerdo, no es muy común que los términos "scripts de administración de sistemas" y "subidón de adrenalina" aparezcan en la misma frase. A no ser, eso sí, que el subidón de adrenalina se refiera a la ausencia total y completa de dichos scripts.

El usuario medio cree que la administración de sistemas es una tarea realmente útil pero probablemente no demasiado excitante; incluso es posible que el scripting le parezca algo bastante latazo. Sin duda, este es el motivo: estas personas no han probado a escribir scripts de datos de configuración de arranque del sistema en Windows Vista® o en Windows Server® 2008.

Oh, sí, eso le ha acelerado el pulso un poco, ¿verdad? Como la mayoría de los que leen estas líneas probablemente ya sepan, en Windows Vista y Windows Server 2008, ya no se usa el antiguo archivo boot.ini, sino que se incluye un nuevo almacén de datos de configuración que proporciona una mayor flexibilidad (y más capacidades) a la hora de administrar el proceso de arranque del sistema.

Eso está muy bien. Pero lo realmente interesante es esto: gracias a un nuevo proveedor WMI (Windows® Management Instrumentation o Instrumental de administración de Windows) y, por medio scripts, ahora puede obtener acceso al almacén de datos de configuración de arranque (BCD) del sistema de un modo sencillo y completamente administrado.

No se extrañe si un escalofrío le recorre la columna de arriba abajo; eso es exactamente un subidón de adrenalina. Una vez que empiece a trabajar con los scripts de BCD, se irá acostumbrando.

Antes de ir más allá, debemos señalar que no podremos cubrir todos los usos posibles del proveedor BCD, al menos no en esta sola columna. Enviamos un correo electrónico a la redacción sobre la posibilidad de realizar un número doble especial dedicado completamente a los scripts de datos de configuración de arranque del sistema, pero aún no hemos recibido respuesta.

Si desea obtener información más completa, consulte la documentación del proveedor WMI de BCD en go.microsoft.com/fwlink/?LinkId=116953. Mientras tanto, le enseñaremos código muestra, diseñado para equipos de arranque múltiple, equipos con varios sistemas operativos.

Por cierto, estos scripts sólo funcionan en Windows Vista y Windows Server 2008. Se debe a que, como decíamos antes, son los únicos sistemas operativos compatibles en la actualidad con BCD.

Comencemos echando un vistazo al script que nos informa del sistema operativo en uso en el equipo. De acuerdo, es cierto que no se trata del uso más interesante del proveedor BCD; al fin y al cabo, también se puede usar la clase WMI Win32_OperatingSystem para determinar el sistema operativo en uso de un equipo. Sin embargo, este es un script bastante sencillo (al menos en lo que a scripts de BCD se refiere) y proporciona un buen método para ilustrar las técnicas básicas necesarias para trabajar con BCD. Técnicas que son, al menos, no tan "comunes".

Además, nuestras columnas no pueden ser excesivamente divertidas: TechNet Magazine ya nos ha advertido que seremos directamente responsables por cualquier perjuicio causado por enfervorizados seguidores sobreestimulados de Hey, Scripting Guy! Teniendo en cuenta las serias repercusiones que originó nuestra columna acerca de las expresiones regulares por todo el mundo, bueno... no nos podemos arriesgar a escribir algo tan excitante de nuevo.

Nota ¿No se acuerda de todos esos vídeos de los Beatles acosados por los fans? Todas esas imágenes de chicas gritando y llorando por John, Paul, George y Ringo... Eso se parece mucho a lo que nos pasa cuando publicamos una nueva columna.

Bueno, vale, quizás sea exagerar un poco. Aunque no cabe duda de que hay un montón de gente (hombres y mujeres por igual) que llegan a llorar de emoción al leer nuestras columnas.

En cualquier caso, eche un vistazo al script de la Figura 1, que usa el proveedor BCD para determinar el SO actualmente en uso en un equipo. Antes de que intente ejecutar el script, tenga en cuenta que debe hacerlo como administrador; de lo contrario, se producirá un error.

Figura 1 Detección del sistema operativo actual

Const BcdLibraryString_Description = &h12000004
Const Current = "{fa926493-6f1c-4193-a414-58f0b2456d1e}"

strComputer = "."

Set objStoreClass = GetObject("winmgmts:{(Backup,Restore)}\\" & _
 strComputer & "\root\wmi:BcdStore")

objStoreClass.OpenStore "", objStore
objStore.OpenObject Current, objDefault

objDefault.GetElement BcdLibraryString_Description, objElement
Wscript.Echo "Current operating system: " & objElement.String

Y no, eso no significa que necesite iniciar sesión con una cuenta con privilegios de administrador. Significa que necesita abrir una ventana del símbolo del sistema (haga clic con el botón secundario en Símbolo del sistema, en el menú Inicio), y seleccionar Ejecutar como administrador. De este modo, ya puede ejecutar el script en el símbolo del sistema.

¿Cómo funciona este script? Ya nos temíamos que haría esa pregunta. Está bien; intentaremos explicarlo lo mejor que podamos (pero intentaremos dejar el nivel de excitación lo más bajo posible).

Comenzamos definiendo dos constantes: BcdLibraryString_Description y Current. BcdLibraryString_Description hace referencia al objeto que deseamos recuperar. En este caso, el objeto contiene la descripción (nombre) del sistema operativo actual.

Esta es, por cierto, una de las peculiaridades de trabajar con el proveedor BCD. Normalmente, no nos limitamos a recuperar el valor de una propiedad, sino que usamos uno de estos valores de constantes (junto con el método GetElement) para recuperar otro objeto y, a continuación, hacer eco del valor de una propiedad que pertenece a dicho objeto. Parece obvio, pero ya sabe lo que se dice: llegar es sólo la mitad del camino.

Nota Lo que de algún modo le hace preguntarse hacia dónde se dirigía en realidad, ¿no?

En lo que respecta a la constante Current, bueno, es sólo un GUID que representa el sistema operativo en uso. El valor

 {fa926493-6f1c-4193-a414-58f0b-2456d1e} 

se considera un GUID "conocido" (una muestra del sano sentido del humor de Microsoft).

A pesar del hecho de que se trata de un GUID bastante común, decidimos incluir el valor de todos modos, sólo por si algún lector no recuerda exactamente cuál de los siguientes dos valores es el correcto:

{fa926493-6f1c-4193-a414-58f0b2456d1e} 
{fa926493-6f1c-4193-a414-58f0b2456d1f}

Nota Quizás le interese saber que GUID se puede pronunciar como "gu idé" o "gu aidí". Podríamos darle mucha más información, como que el GUID anterior debe ser un GUID V1, ya que el tercer grupo de dígitos comienza por un 4 pero, como prometimos, tenemos que mantener el nivel de emoción al mínimo. Y nosotros cumplimos nuestras promesas.

Como puede que haya adivinado, tendrá que usar constantes, valores hexadecimales y GUID por todas partes cuando trabaje con el proveedor BCD. No podemos hablar de todos estos elementos en la columna de este mes, pero puede visitar la página de BCD que mencionamos antes, en MSDN® (go.microsoft.com/fwlink/?LinkId=116953) para obtener más información. Si puede soportar altos niveles de excitación, claro.

Después de definir nuestras dos constantes, conectamos con el servicio WMI en el equipo local. ¿Se puede usar este script para recuperar los datos de configuración de arranque de un equipo remoto? Por supuesto que sí.

Para ser sinceros, si no pudiera, todo esto de BCD tendría una utilidad bastante limitada. Para recuperar los datos de configuración de arranque de un equipo remoto (de nuevo, el equipo remoto debe ejecutar Windows Vista o Windows Server 2008), sólo tiene que asignar el nombre del equipo a la variable strComputer:

strComputer = "atl-fs-001"

también debemos señalar una serie de elementos clave en nuestra cadena de conexión de WMI. Para empezar, quizás se haya dado cuenta de que hemos incluido los privilegios de copia de seguridad y restauración en nuestra cadena de conexión; esa es la función de la construcción {(Backup,Restore)}. ¿Es esto importante? Bueno, si desea que el script funcione, es muy importante: si no incluye de forma explícita estos dos privilegios, el script provocará un error.

En segundo lugar, debe tener en cuenta que no se realiza una conexión con el espacio de nombres root\cimv2, el más común dentro de los scripts de administración de sistemas. En su lugar, conectamos con el espacio de nombres root\WMI y enlazamos directamente con la clase BCDStore. Esa es la función de este fragmento de código:

"\root\wmi:BcdStore" 

Y no, todavía no hemos llegado a la parte emocionante. Lo realmente divertido aún no ha hecho acto de presencia.

Quizás con un par de excepciones, la mayor parte de los scripts de BCD que escriba empezarán con los mismos tres pasos: definir las constantes, conectar con el servicio WMI y, finalmente, abrir el almacén BCD. Ya hemos realizado los pasos 1 y 2. La siguiente línea de código se encarga del paso 3.

objStoreClass.OpenStore "", objStore

Como decíamos, ahora tenemos que abrir el almacén BCD: la entidad del sistema operativo que almacena toda la información de configuración de arranque. Para abrir el almacén, sólo tenemos que llamar al método OpenStore, con estos dos parámetros de métodos:

  • Una cadena vacía (""). Esto indica al script que deseamos abrir el almacén predeterminado.
  • objStore. Este es un parámetro "out" que proporcionamos al script. Damos al método el nombre de una variable y, como muestra de agradecimiento, el método nos devuelve un objeto (que, en este caso, representa el almacén BCD) que usa este nombre de variable como referencia de objeto.

Tan pronto como se abre el almacén, ya se puede usar el método OpenObject para recuperar otro objeto (almacenado en el parámetro out objDefault):

objStore.OpenObject Current, objDefault

¿Y qué cree que es este nuevo objeto? Exacto: el sistema operativo en uso actualmente. Lo sabemos porque transferimos al método OpenObject la constante Current, el famoso GUID que representa el sistema operativo actual.

Muy bien, así que ya sabemos el sistema operativo actualmente en uso en el equipo, ¿verdad? Bueno, casi. Para obtener esta información, aún tenemos que usar GetElement para recuperar un objeto que represente el elemento Description de dicho sistema operativo.

objDefault.GetElement _
  BcdLibraryString_Description, objElement

¿Promete que no se excitará demasiado y provocará algún tipo de desorden público? Bien. En ese caso, le contaremos que ahora podemos hacer eco del valor de la propiedad String para, por fin, determinar el sistema operativo actualmente en uso del equipo:

Wscript.Echo "Current operating system: " _
  & objElement.String

Por favor, cálmese. Recuerde su promesa: nada de altercados. Ya, sabemos que es difícil.... Contrólese como buenamente pueda. Respire profundamente; a nosotros eso siempre nos da resultado cuando escribimos scripts de BCD.

Como decíamos, determinar el sistema operativo actualmente en uso de un equipo implica realizar una serie de tareas más o menos complicadas, pero hay formas más sencillas de lograr el mismo resultado. Si lo mira por el lado bueno, ahora ya sabe cómo funciona un script de BCD, lo que significa que, a partir de ahora, puede hacer cosas que los creadores de scripts nunca han sido capaces de hacer. (Tranquilo... no se altere...) Por ejemplo, en un equipo de arranque múltiple, siempre hay un sistema operativo identificado como "predeterminado". Si el equipo se reinicia, se cargará de forma automática el sistema operativo predeterminado, si no hay nadie cerca que indique lo contrario. Antes de Windows Vista (y del proveedor BCD), no había ninguna forma de que un script identificara el sistema operativo predeterminado de un equipo. Ahora, sin embargo, es tan sencillo como ejecutar un script como el de la Figura 2.

Figura 2 Detección del sistema operativo predeterminado

Const BcdLibraryString_Description = &h12000004
Const BootMgrId = "{9dea862c-5cdd-4e70-acc1-f32b344d4795}"
Const DefaultType = &h23000003

strComputer = "." 

Set objStoreClass = GetObject("winmgmts:{(Backup,Restore)}\\" & _
    strComputer & "\root\wmi:BcdStore")
objStoreClass.OpenStore "", objStore

objStore.OpenObject BootMgrId, objBootMgr 

objBootMgr.GetElement DefaultType, objDefaultOSIdentifier
objStore.OpenObject objDefaultOSIdentifier.Id, objDefault

objDefault.GetElement BcdLibraryString_Description, objElement 
WScript.Echo "Default operating system: " & objElement.String

Sí: esto se merece al menos una pequeña ola de agitación, ¿no? Pero que no tenga mucha altura, ¿de acuerdo? No vamos a explicar este script en una profundidad excesiva: si no se ha saltado los últimos 10 ó 12 párrafos, ya debería ser capaz de analizar la parte lógica por sí mismo. Verá, sin embargo, que, para obtener el sistema operativo predeterminado, hemos introducido un paso intermedio: hemos tenido que usar el método OpenObject para abrir una instancia del objeto del administrador de arranque. Después de abrir el administrador de arranque, podemos usar la constante DefaultType para recuperar un objeto que representa el sistema operativo predeterminado.

Ahora sí. Admitámoslo. Esto sí que pone los pelos de punta: podemos determinar el sistema operativo actual e incluso podemos ver cuál es el predeterminado. Pero... ¿sabe lo que estaría bien de verdad? Obtener una lista de todos los sistemas operativos instalados en un equipo. ¡Eso sí que sería espectacular! Agárrese bien y fíjese en la Figura 3.

¿Qué estamos haciendo en este caso? Bueno, para empezar, definimos dos constantes nuevas: WindowsImages, que nos permite recuperar instancias de todos los sistemas operativos compatibles con BCD (o sea, Windows Vista y Windows Server 2008), y LegacyImages, que nos permite recuperar instancias de los sistemas operativos "heredados" del equipo. Tras conectar con el almacén BCD, usamos el método EnumerateObjects para recuperar todas las instancias de los sistemas operativos compatibles con BCD instalados en el equipo:

objStore.EnumerateObjects _
  WindowsImages, colObjects 

Figura 3 Obtención de todos los sistemas operativos de un equipo

Const BcdLibraryString_Description = &h12000004
Const WindowsImages = &h10200003
Const LegacyImages = &h10300006

strComputer = "."

Set objStoreClass = GetObject("winmgmts:{(Backup,Restore)}\\" & _
 strComputer & "\root\wmi:BcdStore")

objStoreClass.OpenStore "", objStore 

objStore.EnumerateObjects WindowsImages, colObjects 

For Each objObject in colObjects
 objObject.GetElement BcdLibraryString_Description, objElement 
 Wscript.Echo objElement.String
Next
Wscript.Echo

objStore.EnumerateObjects LegacyImages, colObjects 

For Each objObject in colObjects
 objObject.GetElement BcdLibraryString_Description, objElement 
 Wscript.Echo objElement.String
Next

Después de que EnumerateObjects haga su trabajo, deberemos configurar un bucle For Each que pase por todos los sistemas operativos de dicha recopilación. Dentro de este bucle, usamos estas dos líneas de código para recuperar y, a continuación, mostrar el elemento Description, referente al sistema operativo:

objObject.GetElement _
  BcdLibraryString_Description, objElement 
Wscript.Echo objElement.String

A continuación, repetimos el proceso para todos los sistemas operativos heredados que haya instalados en el equipo:

objStore.EnumerateObjects _
  LegacyImages, colObjects 

For Each objObject in colObjects
 objObject.GetElement _
  BcdLibraryString_Description, objElement 
 Wscript.Echo objElement.String
Next

Nota Sabemos que pedimos mucho, pero trate de hacer un uso responsable de sus scripts de BCD; es más que probable que haya un límite para la cantidad de adrenalina que puede soportar un cuerpo humano. Las mujeres embarazadas, las que estén pensando en quedarse embarazadas, las que en algún momento hayan estado embarazadas, las que nunca vayan a estar embarazadas e incluso las que no sean mujeres, sino hombres, no deberían usar scripts de BCD sin consultar antes con su médico.

Venga, está bien, no hace falta que hable con su médico. Pero sería interesante conocer la opinión de un médico respecto a la ejecución de scripts de BCD, ¿verdad?

Ahora vamos a tirar la casa por la ventana: vamos a intentar cambiar el sistema operativo predeterminado. Por ejemplo, suponga que tenemos un equipo de arranque dual que ejecuta Windows Vista y Windows Server 2008, y queremos que Windows Vista sea el sistema operativo predeterminado. ¿Cómo podríamos hacer eso? Eche un vistazo a la Figura 4. Muestra una forma de llevar a cabo esta tarea.

Figura 4 Cambio del sistema operativo predeterminado

Const BootMgrId = "{9dea862c-5cdd-4e70-accl-f32b344d4795}"
Const BcdLibraryString_Description = &h12000004
Const DefaultType = &h23000003
Const WindowsImages = &h10200003

strComputer = "."

Set objStoreClass = GetObject("winmgmts:{(Backup,Restore)}\\" & _
 strComputer & "\root\wmi:BcdStore")

objStoreClass.OpenStore "", objStore 
objStore.EnumerateObjects WindowsImages, colObjects 

For Each objObject in colObjects
 objObject.GetElement BcdLibraryString_Description, objElement 
 If Instr(objElement.String, "Vista") Then
  objStore.OpenObject BootMgrId, objBootMgr 
  objBootMgr.SetObjectElement DefaultType, objObject.ID 
 End If
Next

Con este script, de nuevo abrimos el almacén BCD para, a continuación, usar el método EnumerateObjects para recuperar una recopilación de todos los sistemas operativos compatibles con BCD que están instalados en el equipo. Seguidamente, configuramos un bucle For Each para que pase por todos los elementos de la recopilación, mediante la siguiente línea de código (que ya parece familiar), para recuperar el elemento Description de cada sistema operativo:

objObject.GetElement _
  BcdLibraryString_Description, objElement

Tan pronto como obtenemos dicho elemento para un sistema operativo determinado, usamos la función InStr para ver si la palabra Vista aparece en dicho valor:

If Instr(objElement.String, "Vista") Then

Tiene razón, parece un poco "precario", ¿no? Lo interesante sería usar el GUID de Windows Vista y abrir directamente el sistema operativo sin tener que enumerar y pasar por todos los sistemas operativos del equipo.

Por desgracia, este método tan atractivo requiere que conozcamos el GUID de Windows Vista. En cambio, de este modo, no hace falta saber nada (lo que es siempre un plus para los Scripting Guys); todo lo que tenemos que hacer es buscar hasta que encontremos un sistema operativo con la palabra Vista en el título.

Nota ¿Qué pasa si hay varias versiones de Windows Vista instaladas en un mismo equipo? Bueno, en ese caso, deberemos buscar una cadena como Vista Ultimate o Vista Enterprise.

En cuanto encontremos Windows Vista, usamos estas dos líneas de código para abrir el administrador de arranque de Windows y, a continuación, establecemos el sistema operativo predeterminado en Windows Vista:

objStore.OpenObject BootMgrId, objBootMgr 
objBootMgr.SetObjectElement _
  DefaultType, objObject.ID 

Sólo tenemos tiempo para esto este mes; después de todo, ni siquiera los mismos Scripting Guys tienen la capacidad de lidiar con estos niveles de agitación las 24 horas del día, los 7 días de la semana. Pero no se preocupe, volveremos el mes que viene con otra emocionante entrega de Hey, Scripting Guy! Con algo de suerte, se habrá recuperado para entonces.

Dr. Scripto's Scripting Perplexer

El desafío mensual que prueba no sólo sus habilidades para resolver rompecabezas, sino también sus habilidades para el scripting.

Julio de 2008: cuadrados de VBScript

Vale, parecen más rectángulos, no cuadrados, pero eso da igual. Para resolver este puzzle, coloque todos los cuadrados de la derecha en los cuadrados vacíos de la izquierda con el fin de crear los nombres de las funciones VBScript. Cada cuadrado sólo se puede usar una vez. Por ejemplo:

para resolver correctamente este puzzle, tiene que mover el cuadrado OU (bueno, rectángulo) al cuadrado en blanco de la primera palabra, y MS y OX a los cuadrados en blanco de la segunda palabra. Esto crea las funciones UBound y MsgBox de VBScript, como aparece aquí:

Su turno:

RESPUESTA:

Dr. Scripto's Scripting Perplexer

Respuesta: Cuadrados de VBScript, julio de 2008

Los Scripting Guys trabajan para... bueno, son empleados de Microsoft. Cuando no están jugando o viendo béisbol (entre otras muchas actividades), dirigen el TechNet Script Center. Visite la página web www.scriptingguys.com.

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