¡Hola, encargados del scripting!Nuestros juegos de shell favoritos

Los chicos del scripting de Microsoft

Descargar el código de este artículo: HeyScriptingGuy2008_03.exe (150KB)

Según un proverbio antiguo, ni tan siquiera el gorrión más diminuto puede caer al suelo sin que lo sepan los cielos. Con esto, los chicos del scripting no quieren decir que la gente vaya por ahí matando gorriones. Aunque si hay alguien que quiera ocuparse de esos cuervos que se posan en el tejado y empiezan a graznar a las 7:00 de la mañana todos los sábados..., eso es un cuento diferente. (El editor de scripting adora los cuervos, así que estamos seguros de que, al decir "ocuparse", el chico del scripting que escribe esta columna quiere decir "asegurarse de que están sanos." -El editor) No obstante, es todo un alivio saber que, si se cae, hay a quien le importa y que, por pequeño e insignificante que parezca, hay quien está pendiente de lo que pueda pasarle. (Aunque se trate de un simple editor. -El editor)

Lo que se aplica a los gorriones resulta ser verdadero también en materia de scripting para administración de sistemas. Se puede decir que, en el mundo del scripting, la mayor parte de la atención se centra en los grandes kahunas del scripting: Windows PowerShellTM, VBScript, WMI, ADSI e, incluso, FileSystemObject. Es comprensible que estas tecnologías se lleven todo el mérito y la publicidad. A fin de cuentas, permiten hacer muchas cosas útiles y maravillosas. Pero eso no significa que estas sean las únicas tecnologías disponibles para trabajar con scripts. Ni mucho menos.

Tomemos el objeto Shell como ejemplo. Aunque el objeto Shell no es tan conocido ni popular como Windows PowerShell, es útil e importante.

Hay muchas posibilidades de que, tarde o temprano, alguien le pedirá que escriba un script de administración del sistema que usa el objeto Shell. Esto da origen a una pregunta obvia: ¿Qué se puede hacer exactamente con el objeto Shell? Resulta que hay muchas cosas fantásticas que se pueden hacer con el objeto Shell. Algunas de ellas (por ejemplo, administrar la cuota de disco y mostrar una barra de progreso durante la copia o el traslado de archivos) ya se han descrito en Microsoft® Windows® 2000 Scripting Guide (microsoft.com/technet/scriptcenter/guide). En la columna de este mes, le mostraremos algunas otras cosas ingeniosas que puede hacer con el objeto Shell, cosas que probablemente no tenía ni la menor idea de que podían hacerse en absoluto, mucho menos con el objeto Shell.

Cambios en la fecha de última modificación de un archivo

Seguro que hay quien se queda mirando este título anterior y piensa: "Oye, espera un segundo. No se puede cambiar la fecha de última modificación de un archivo con un script, por lo menos, eso no se puede hacer con VBScript". A esto, solamente podemos decir una cosa: ¿De dónde ha sacado semejante idea?

Ya sé; seguramente eso es algo que los chicos del scripting hemos dicho en el pasado. Bueno, pues resulta que estábamos equivocados. ¡Qué sorpresa, ¿eh?! Es posible cambiar la fecha de última modificación de un archivo con VBScript. Y todo lo que hay que hacer es usar el objeto Shell.

Nota: no se moleste en preguntar cómo es posible que los chicos del scripting se equivocaran en algo así; después de todos estos años, eso debería ser obvio. Una pregunta mucho más interesante es esta: ¿Cómo nos las arreglamos para hacer algo bien en ocasiones?

Así que desea cambiar la fecha de última modificación de un archivo, ¿eh? Entonces, use este script:

Set objShell = _
  CreateObject("Shell.Application")

Set objFolder = _
  objShell.NameSpace("C:\Scripts")
Set objFolderItem = _
  objFolder.ParseName("Dr_Scripto.jpg")

objFolderItem.ModifyDate = _
  "01/01/2008 8:00:00 AM"

Como puede ver, no hay nada terriblemente complicado en el asunto. Empezamos por crear una instancia del objeto Shell.Application. A propósito, no confunda Shell.Application con Wscript.Shell, el objeto Shell de Windows Script Host. El objeto Shell con que trabajamos hoy es el objeto Shell de Windows. Una vez que nuestra instancia del objeto Shell está en funcionamiento, usamos el método Namespace para enlazar a la carpeta C:\Scripts y, luego, usamos el método ParseName, con un nombre un tanto extraño, para enlazar a un archivo específico dentro de dicha carpeta. En este caso, enlazamos a una imagen JPEG con el nombre de archivo Dr_Scripto. jpg:

Set objFolderItem = _
  objFolder.ParseName("Dr_Scripto.jpg")

¿Y qué hacemos después de enlazar al archivo mismo? Eso es fácil; simplemente asignamos una fecha y una hora nuevas a la propiedad ModifyDate:

objFolderItem.ModifyDate = _
  "01/01/2008 8:00:00 AM"

Eso es todo lo que debemos hacer.

Sabe, tiene razón. Eso es fantástico. Una vez que ejecutamos el script, la fecha de última modificación del archivo estará establecida en 01/01/08 8:00. Si lo desea, puede abrir la carpeta C:\Scripts en el Explorador de Windows para comprobarlo.

Por supuesto, habrá quien esté pensando: "Perfecto. Es posible cambiar la fecha de última modificación de un archivo. Pero, ¿por qué querría cambiar la fecha de última modificación de un archivo? Mucha gente usa la fecha de última modificación de los archivos como sistema de control de versiones. Por ejemplo, si tiene varias copias de un script, una forma de realizar el seguimiento de la versión oficial es comprobar la fecha de última modificación. Así, sabrá que una copia particular del script es una versión sin modificar del script original.

Nota: de acuerdo, lo sabemos, alguien puede ejecutar el script que acabamos de mostrar y cambiar la fecha de última modificación. Pero, a menos que firme todo lo que hace mediante código, siempre se puede encontrar alguna manera de vencer al sistema. Si damos por sentado que los compañeros con los que comparte los scripts son de confianza, este es un enfoque razonable.

En algún momento, quizás decida que desea actualizar, y estandardizar, la fecha de última modificación de todos sus scripts. ¿Cómo puede hacerlo? Bien, si todos sus scripts están en la carpeta C:\Scripts, puede ejecutar el código siguiente:

Set objShell = _
  CreateObject("Shell.Application")

Set objFolder = _
  objShell.NameSpace("C:\Scripts")
Set colItems = objFolder.Items

For Each objItem In colItems
    objItem.ModifyDate  = _
      "01/01/2008 8:00:00 AM"
Next

Como puede ver, este script empieza de forma muy semejante al primer script que mostramos. Sin embargo, en este caso, después de enlazar a la carpeta C:\Scripts, no usamos ParseName para enlazar a un archivo individual en esta carpeta. En su lugar, usamos esta línea de código para devolver una colección de todos los archivos en la carpeta:

Set colItems = objFolder.Items

Una vez que tenemos la colección, configuramos un bucle For Each que pase por todos los elementos de la colección. Dentro del bucle For Each, usamos esta práctica línea de código para cambiar el valor de la propiedad ModifyDate del primer archivo de la colección a 01/01/08 8:00:

objItem.ModifyDate  = _
  "01/01/2008 8:00:00 AM"

A continuación, simplemente pasamos el bucle y repetimos el proceso con el siguiente archivo de la colección. Al terminar, todos los archivos de la carpeta C:\Scripts (bueno, excepto los archivos ocultos) tendrán la misma fecha de última modificación. ¿Ve que fácil es? Entonces, ¿quién ha dicho que no es posible cambiar la fecha de última modificación de un archivo con VBScript?

Ah, cierto.

Hablando de meter la pata...

En un tiempo inmemorable, cuando los chicos del scripting empezaron a trabajar con scripting de administración de sistemas, no había manera de obtener acceso a toda la información extendida que se asocia a los archivos en el sistema de archivos NTFS. Por ejemplo, si hace clic con el botón secundario en un archivo .wav y luego en Propiedades, verá información semejante a la que muestra la Figura 1.

Figura 1 Resumen de propiedades de archivo

Figura 1** Resumen de propiedades de archivo **

¿Cómo se pueden recuperar valores, como la velocidad de bits o el tamaño de muestra de sonido, mediante un script? No se puede. Bueno, no se puede a menos que usemos el objeto Shell. O Windows Desktop Search 3.0, si ha descargado e instalado el software. En algún momento, se agregó al objeto Shell la capacidad de recuperar toda la información de propiedades extendidas de los archivos, pero los chicos del scripting no se percataron del hecho. Consecuentemente, hemos estado diciendo a la gente: "No se puede usar un script para determinar la velocidad de bits de un archivo .wav", aunque, como demuestra el código de la Figura 2, sí que se puede.

Figure 2 Use un script para encontrar la velocidad de bits de un archivo .wav

Set objShell = CreateObject("Shell.Application")

Set objFolder = objShell.NameSpace("C:\Scripts")
Set objFolderItem = objFolder.ParseName("J0388563.wav")

For i = 0 to 33
    strHeader = objFolder.GetDetailsOf(objFolder.Items, i)
    strValue = objFolder.GetDetailsOf(objFolderItem, i)
    If strValue <> "" Then
        Wscript.Echo strHeader & vbTab & strValue
    End If
Next

¿Cómo funciona este script? Bien, este también empieza como el primer script que mostramos: creamos una instancia del objeto Shell.Application y enlazamos a la carpeta C:\Scripts; después, usamos el método ParseName para enlazar al archivo en cuestión (en este caso, J0388563.wav).

Ahora, las cosas se complican un poco. Para empezar, configuramos un bucle For Next que se ejecute de 0 a 33, ya que los archivos admiten un máximo de 31 propiedades extendidas diferentes a las que se han asignado números de índice de 0 a 33. Fíjese que hay algunos números, como 27 y 28, que son números de índice válidos pero que no contienen ningún valor de propiedad. De hecho, los archivos admiten las propiedades mostradas en la Figura 3.

Figure 3 Propiedades de archivo

Índice Propiedad
0 Nombre
1 Tamaño
2 Tipo de archivo
3 Modificado
4 Creado
5 Último acceso
6 Atributos
7 Estado
8 Propietario
9 Autor
10 Título
11 Asunto
12 Categoría
13 Páginas
14 Comentarios
15 Copyright
16 Intérprete
17 Álbum
18 Año
19 Número de pista
20 Género
21 Duración
22 Velocidad de bits
23 Modo protegido
24 Modelo cámara
25 Fecha de captura
26 Dimensiones
29 Episodio
30 Descripción del programa
32 Tamaño de muestra de sonido
33 Velocidad de muestra de sonido

Así que, ¿qué hacemos dentro del bucle For Next? Bien, lo primero es ejecutar esta línea de código:

strHeader = _
  objFolder.GetDetailsOf(objFolder.Items, i)

Aquí, usamos el método GetDetailsOf para recuperar el nombre de la propiedad 0 (recuerde, nuestro bucle se ejecuta de 0 a 33). Entonces almacenamos este nombre en una variable denominada strHeader; usamos esta línea de código para recuperar el valor de propiedad del elemento 0 y almacenamos la información devuelta en una variable denominada strValue:

strValue = _
  objFolder.GetDetailsOf(objFolderItem, i)

¿Ahora entiende cómo funciona? El elemento 0 resulta ser la propiedad Name. De modo que, la primera vez que pasa por el bucle, strHeader será igual a Name. Mientras tanto, el nombre real (es decir, el valor de la propiedad Name) del primer archivo es J0388563.wav. Por lo tanto, la primera vez que pasa por el bucle, strValue será igual a J0388563.wav. Si lo ponemos así, no parece tan complicado, ¿verdad?

Como probablemente sabe, no todos los tipos de archivo admiten todas las propiedades extendidas. Por ejemplo, un archivo .jpg no presentará título de álbum ni velocidad de muestra de sonido. Por lo tanto, en la siguiente línea de código, comprobamos si un valor devuelto es una cadena vacía:

If strValue <> "" Then

Si el valor es una cadena vacía, simplemente volvemos al principio del bucle y repetimos el proceso con la propiedad extendida siguiente. Si el valor no es una cadena vacía, devolvemos el valor y el nombre de la propiedad, así:

Wscript.Echo strHeader & vbTab & strValue

¿El resultado final? Algo muy semejante a esto:

Name    j0388563.wav
Size    169 KB
Type    Wave Sound
Date Modified   1/19/2004 8:56 AM
Date Created    3/6/2006 2:02 PM
Date Accessed   12/3/2007 10:41 AM
Attributes      A
Status  Online
Owner   FABRIKAM\kenmyer
Bit Rate        90kbps
Audio Sample Size       4 bit
Audio Sample Rate       11 kHz

Interesante.

No nos queda mucho tiempo (ni espacio) pero, si busca una manera todavía más fácil de devolver los valores de propiedad más pertinentes, pruebe el script de la Figura 4.

Figure 4 Una manera fácil de devolver valores de propiedad

Const colInfoTip = -1

Set objShell = CreateObject("Shell.Application")

Set objFolder = objShell.NameSpace("C:\Scripts")
Set objFolderItem = _
  objFolder.ParseName("01. Out On The Weekend (Album Version).wma)")

Wscript.Echo objFolder.GetDetailsOf(objFolderItem, colInfoTip)

¿Qué hace este script? Si se encuentra en el Explorador de Windows y mantiene el cursor del mouse sobre un archivo, aparecerá información sobre herramientas que ofrece datos útiles acerca del archivo, como muestra la Figura 5. ¿Cómo se puede obtener esta información sobre herramientas mediante un script? Exacto. Use el script que acabamos de mostrarle:

Figura 5 Propiedades mostradas mediante información sobre herramientas

Figura 5** Propiedades mostradas mediante información sobre herramientas **

Artist: Neil Young
Album Title: Harvest
Year: 1972
Track Number: 1
Duration: 0:04:35
Type: Windows Media Audio file
Bit Rate: 256kbps
Protected: Yes
Size: 5.31 MB 

Y ya no tenemos más tiempo por este mes. Bueno, tenemos tiempo para una última nota sobre los gorriones. Una razón por la que quizás desee prestar atención a los gorriones diminutos es esta: en algunas partes del mundo, se considera mala suerte que un gorrión entre en la casa. ¿Por qué? Significa que alguien que vive en la casa va a morir. En algunos casos, eso sólo es verdad si el gorrión aterriza sobre un piano. Pero eso no es una superstición, es sólo algo muy raro. Pero aquí viene la parte interesante: en otras partes del mundo, si un gorrión entra en la casa, significa que alguien que vive en la casa va a casarse. ¿Qué le parece la diferencia, eh?

Dr. Scripto's Scripting Perplexer

El desafío mensual que prueba no sólo sus habilidades de resolución de rompecabezas, sino también sus habilidades de creación de scripts.

Marzo de 2008: Script críptico

El rompecabezas de este mes es un criptograma, lo que significa que cada letra se ha reemplazado por una letra diferente. Hemos dejado todos los símbolos y los números intactos. Una letra siempre representará la misma letra reemplazada. Por ejemplo, todas las repeticiones de la letra a podrían quedar reemplazadas por la letra b; todas las repeticiones de la letra b podrían quedar reemplazadas por la letra z, etc. He aquí un ejemplo simple:

tdsjqu dfoufs

se convierte en esto:

script center

En este caso, la descodificación se consigue al reemplazar cada letra con la letra del alfabeto que la precede, de modo que t queda reemplazada por s, d queda reemplazada por c, etc.

Nuestro rompecabezas es un poco más difícil. Descodifique este script y obtendrá un script que abre Microsoft Excel®, agrega una hoja de cálculo nueva, asigna cuatro valores a la primera columna en la hoja de cálculo y ordena dicha columna en orden ascendente.

Diviértase.

El rompecabezas

kqyjs edfjkzyrlyg = 1
kqyjs edyq = 2
kqyjs edjqtstqmj = 2

jzs quwzekzd = ktzfszquwzks("zekzd.faadlkfslqy")
quwzekzd.iljludz = stcz

jzs quwmqtxuqqx = quwzekzd.mqtxuqqxj.frr
jzs quwmqtxjozzs = quwmqtxuqqx.mqtxjozzsj(1)

quwmqtxjozzs.kzddj(1, 1) = "kfs"
quwmqtxjozzs.kzddj(1, 2) = "rqg"
quwmqtxjozzs.kzddj(1, 3) = "ufs"
quwmqtxjozzs.kzddj(1, 4) = "faz"

jzs quwtfygz = quwzekzd.fkslizkzdd.zysltztqm
quwtfygz.jqts quwtfygz, edfjkzyrlyg, , , , , , edyq, , , edjqtstqmj

ANSWER:

Dr. Scripto's Scripting Perplexer

Respuesta: Sript críptico, marzo de 2008

Aquí está la clave para descodificar el script:

Actual Letter   a   b   c   d   e   f   g   h   i   j   k
Coded Letter    f   u   k   r   z   b   g   o   l   w   x

Actual Letter   l   m   n   o   p   q   r   s   t   u   v   w   x   y   z
Coded Letter    d   n   y   q   a   h   t   j   s   c   i   m   e   v   p

Y aquí tiene el script descodificado:

Const xlAscending = 1
Const xlNo = 2
Const xlSortRows = 2

Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = True

Set objWorkbook = objExcel.Workbooks.Add
Set objWorksheet = objWorkbook.Worksheets(1)

objWorksheet.Cells(1, 1) = "Cat"
objWorksheet.Cells(1, 2) = "Dog"
objWorksheet.Cells(1, 3) = "Bat"
objWorksheet.Cells(1, 4) = "Ape"

Set objRange = objExcel.ActiveCell.EntireRow
objRange.Sort objRange, xlAscending, , , , , , xlNo, , , xlSortRows

Los chicos del scripting de MicrosoftLos chicos del scripting trabajan para Microsoft, mejor dicho, están contratados por Microsoft. Cuando no juegan al béisbol, ni entrenan ni lo ven (u otras actividades varias), dirigen el TechNet Script Center. Visite la página web www.scriptingguys.com.

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