¡Hola, chicos del scripting!Dominio inocente de los usuarios y grupos locales

Los chicos del scripting de Microsoft

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

¿Cómo puedo administrar descriptores de seguridad en archivos y carpetas?

Aunque no se lo crea, hubo un tiempo (hace mucho tiempo, por supuesto) en el que los chicos del scripting no eran demasiado listos. Sabemos que es difícil de creer, pero, ¿qué quiere decir con que no es tan difícil de creer? ¿Y qué significa eso de que no puede haber sido hace tanto tiempo? Deje que le digamos que... bueno, vale. Obviamente, vio a uno de los chicos del scripting intentando conectar un televisor nuevo el otro día.

En su defensa, este chico del scripting argumentaría que conectar un televisor nuevo no es ingeniería espacial, sino que es mucho más complicado. Sólo para conectar el televisor se necesitan tres cables de vídeo y un par de cables de audio; además, hay que conectar un reproductor de vídeo, un reproductor de DVD y una consola Xbox®, sin mencionar el tener que presionar toda una serie de números en el mando a distancia "universal" para que pueda reconocer todos estos dispositivos. En comparación con eso, colocar un satélite en órbita alrededor de Marte es pan comido.

Hay que decir que el chico del scripting consiguió realizar todas estas conexiones correctamente. Sin embargo, cuando encendió todos los aparatos, no pasó nada. Diligentemente, revisó y volvió a revisar todas las conexiones. Leyó todos los manuales de usuario e incluso buscó en Internet por si había información que le faltaba. Nada de nada. Ya iba a sacrificar un reproductor de MP3 al dios de la electrónica cuando se dio cuenta de que no había realizado el paso fundamental de conectar el cable que va desde la caja de cables al enchufe de la pared.

Nota: quizás esté pensando que si conectar todo el material de la familia del scripting es tan difícil, puede que la familia del scripting tenga demasiado material. Ciertamente, el chico del scripting estaría de acuerdo con usted. Sin embargo, cada vez que la familia vota sobre la adquisición de más material, este chico del scripting pierde por dos a cero. Y no, no tendría que ser por dos a uno, es dos a cero. Por algún motivo, el voto del padre del scripting parece que no cuenta nunca en las elecciones familiares, y no hay rastro de papel que valga.

En respuesta a su siguiente pregunta: sí, lo ha intentado. Pero hasta ahora la ONU ha rechazado el envío de observadores para supervisar las elecciones en la casa del scripting.

Por supuesto, pensándolo mejor, no es que los chicos del scripting (mejor dicho, el que intentaba instalar el televisor) fueran tontos, es que eran inocentes. Por ejemplo, cuando planeaban el manual de scripting de Microsoft® Windows® 2000, solicitaron ayuda a varios expertos para determinar cuáles serían los capítulos del libro. Uno de los capítulos que se quedó en el tintero fue un capítulo sobre la administración de usuarios y grupos locales. "¿Administrar usuarios y grupos locales?", dijeron los expertos. "¿Por qué tan siquiera se contempla incluir eso? ¿A quién le importa la administración de usuarios y grupos locales?"

Pues bien, muy a nuestro pesar, hemos descubierto que a todo el mundo (con la posible excepción de nuestros "expertos" internos) le importan los usuarios y grupos locales. Cada semana recibimos muchísimos correos electrónicos de personas que preguntan cómo hacer cosas como agregar un usuario a un grupo local, eliminar un usuario de un grupo local o cambiar la contraseña del administrador local en un equipo.

Si bien es cierto que el Repositorio de Script Center tiene algunos scripts de ejemplo que muestran cómo realizar estas tareas, la mayoría de estos scripts funcionan sólo en un equipo a la vez. Eso no es lo suficientemente bueno: los usuarios quieren saber cómo hacerlo en varios equipos simultáneamente. ¿Cambiar la contraseña del administrador local en un sólo equipo? Acérquense al mundo real, chicos del scripting: queremos hacerlo en todos los equipos o en todos los equipos de una unidad organizativa o en... bueno, ya nos entienden.

Teniendo en cuenta que el manual de scripting se publicó en 2003, hemos pasado casi cuatro años recibiendo estos mismos mensajes de correo electrónico. "Aquí hay otro lector que pregunta cómo puede leer nombres de equipo desde una hoja de cálculo de Excel® y, a continuación, cambiar la contraseña del administrador local en cada uno de esos equipos", observó recientemente uno de los chicos del scripting. "¿Qué podemos hacer?"

Bien, nos llevó cuatro años, pero al fin lo averiguamos. En la Figura 1 se muestra exactamente qué podemos hacer.

Figure 1 Finalmente lo averiguamos.

On Error Resume Next

Set objExcel = CreateObject(“Excel.Application”)
Set objWorkbook = objExcel.Workbooks.Open(“C:\Scripts\Test.xls”)
objExcel.Visible = True

i = 2

Do Until objExcel.Cells(i, 1).Value = “”
    strComputer = objExcel.Cells(i, 1).Value   
    Set objUser = GetObject(“WinNT://” & strComputer & “/Administrator”)
    If Err = 0 Then
         objUser.SetPassword “egTY634!alK2”
         objExcel.Cells(i, 2).Value = Now
    End If
    Err.Clear
    i = i + 1
Loop

Nota: como puede observar, no tardamos cuatro años en escribir este script porque fuera difícil, sino porque solemos tardar ese tiempo en hacer cualquier cosa. Por eso uno nunca quiere perderse las fiestas de nochevieja anuales de los chicos del scripting; a fin de cuentas, nunca se sabe cuándo o si se celebrará el próximo acontecimiento anual.

Lo que vemos aquí es un script que extrae los nombres de los equipos de una hoja de cálculo y, a continuación, cambia la contraseña del administrador local en cada uno de esos equipos. Para hacer este truco de magia, empezamos fácilmente, dando por supuesto que tiene una hoja de cálculo muy sencilla, como la de la Figura 2. (Si no la tiene, créela ahora mismo).

Figura 2 Lista obligatoria de equipos

Figura 2** Lista obligatoria de equipos **(Hacer clic en la imagen para ampliarla)

Como puede ver, no tiene nada de especial. En la columna 1 (la columna A), incluimos una lista de los nombres de todos los equipos que tienen las contraseñas que necesitamos cambiar. En la columna 2 (la columna B), simplemente realizamos el seguimiento de la fecha y hora en que se cambió por última vez la contraseña del administrador de cada equipo. Esto le permite saber si todas sus contraseñas de administrador están sincronizadas.

En cuanto al script en sí mismo, empezamos con la instrucción On Error Resume Next. Generalmente, no nos molestamos en incluir el control de errores en nuestros scripts. No es porque nos opongamos al control de errores, sino porque intentamos que nuestros scripts sean lo más breves y sencillos posibles. En este caso, sin embargo, la instrucción On Error Resume Next es crucial. A fin de cuentas, nuestro script intentará conectarse a numerosos equipos distintos. ¿Qué sucede si uno de esos equipos está apagado? Pues con el control de errores no pasará nada. Es cierto, se producirá un error, pero el script podrá omitirlo y continuar. Sin el control de errores obtendría casi el mismo resultado que obtuvo el chico del scripting cuando encendió el nuevo televisor por primera vez: nada.

Lo siguiente es usar el siguiente bloque de código para crear una instancia del objeto Excel.Application, hacer que esa instancia de Excel esté visible en pantalla y abrir la hoja de cálculo C:\Scripts\Test.xls:

Set objExcel = CreateObject _
    (“Excel.Application”)
Set objWorkbook = objExcel.Workbooks.Open _
    (“C:\Scripts\Test.xls”)
objExcel.Visible = True

Y, por último, asignamos el valor 2 a una variable de contador denominada i. Usaremos esta variable para realizar un seguimiento de la fila actual en la hoja de cálculo.

Nota: ¿por qué se le asigna el valor 2? Muy sencillo: si observa de cerca la hoja de cálculo verá que los datos empiezan en la fila 2. La fila 1 es únicamente una fila de encabezado.

¿Lo ve? Quizás no seamos buenos a la hora de conectar cables YPbPr1, pero sí que sabemos algo del scripting.

Bueno, a veces.

Ahora estamos listos para empezar a trabajar. Primero, configuramos un bucle Do Unitl que se ejecute hasta detectar una celda vacía en la columna 1. Y sí, esto significa que, haga lo que haga, no puede dejar ninguna fila en blanco en la columna 1. Si el script detecta una fila en blanco, dará por supuesto que ha alcanzado el final de los datos, por lo que el bucle y el script finalizarán. Aunque hay formas de solucionar esta cuestión, es mucho más sencillo evitar tener filas en blanco en la hoja de cálculo.

Dentro del bucle, empezaremos por asignar el valor encontrado en la fila de celda i, columna 1, a una variable denominada strComputer. Recuerde que la primera vez que pasa por el bucle, i es igual a 2; por lo que trabajaremos con el valor de la celda 2, columna 1. Usaremos esta línea de código para crear una referencia a objeto (objUser) a la cuenta del administrador local del equipo representado por la variable strComputer:

Set objUser = GetObject(“WinNT://” & _
    strComputer & “/Administrator”)

Si se tiene que producir algún error en este script, será en este punto. Por ejemplo, supongamos que tenemos problemas de red, que el equipo se ha apagado o que uno de los chicos del scripting ha conectado mal el reproductor de DVD y ha dejado sin suministro eléctrico a la mitad occidental de Estados Unidos. Si sucede cualquiera de estas cosas, no se podrá establecer una conexión con el equipo. Por este motivo, comprobaremos inmediatamente el valor del objeto Err de VBScript:

If Err = 0 Then

Si el objeto Err es igual a 0, significa que se pudo establecer la conexión con el equipo (y con la cuenta de administrador) sin ningún problema. Si el valor de Err es distinto de 0, sólo puede significar una cosa: se produjo algún error en nuestro intento de conexión. En ese caso, no nos molestaremos en cambiar la contraseña del equipo en cuestión; sobra decir que si no podemos establecer la conexión, no podremos cambiar la contraseña.

Suponiendo que todo vaya bien y que no se produzca ningún error, a continuación, ejecutaremos las dos líneas de código siguientes:

objUser.SetPassword “egTY634!alK2”
objExcel.Cells(i, 2).Value = Now

En la línea 1, usamos el método de SetPassword para asignar una contraseña nueva (egTY634!alK2) a la cuenta del administrador local. (Sí, sí, lo sabemos: se supone que no debe usar el nombre de su hijo como contraseña.) En la línea 2, escribiremos la fecha y la hora actuales (con la función Now de VB-Script) en la fila de la celda i, columna 2. Advierta que actualizamos la columna Password Changed (Contraseña cambiada) sólo si podemos conectarnos al equipo remoto y cambiamos la contraseña. Si no podemos conectarnos a un equipo, su campo Password Changed correspondiente no se actualizará nunca; de esta forma, podemos saber si las operaciones se realizaron correctamente o no.

¿Qué significa todo esto? Esto significa que, la primera vez que pase por el bucle, la hoja de cálculo tendrá un aspecto parecido al de la Figura 3.

Figura 3 Lista de equipos después de restablecer la primera contraseña

Figura 3** Lista de equipos después de restablecer la primera contraseña **(Hacer clic en la imagen para ampliarla)

El equipo 1 ya está. Ahora tenemos que hacer un poco de limpieza antes de continuar:

Err.Clear
i = i + 1

Aunque son muy cortas, estas dos líneas de código son muy importantes. (¡Cómo si los chicos del scripting fueran a escribir líneas de código que no fueran importantes!) La primera línea restablece el objeto Err a 0. Si no se produjo ningún error, esto es redundante; a fin de cuentas, en ese caso Err ya será 0. Si se produjo un error, sin embargo, Err será igual a un valor distinto de 0. En ese caso, es crucial restablecer manualmente el objeto Err. ¿Por qué? Porque se trata del objeto Error: sólo realiza el seguimiento de los errores, no de las acciones realizadas correctamente. Por ejemplo, supongamos que se produjo un problema con el equipo 1 y que no se pudo establecer una conexión. Digamos que esto hizo que el objeto Error se estableciera en 99.

Supongamos también que pasamos por alto este error con el bucle y nos conectamos correctamente al equipo 2. ¿Cuál cree que será el valor de Err ahora? Correcto: nos guste o no, el valor de Err seguirá siendo 99, porque el valor del objeto Err sólo cambia cuando se produce un error; no obstante, si no se produce ningún error, el objeto de Err seguirá conservando su valor actual indefinidamente.

¿Nos importa de verdad? Debería importarnos. A fin de cuentas, técnicamente no cambiamos la contraseña en un equipo si se establece una conexión correctamente; sólo cambiamos la contraseña si Err es igual a 0. Y (un momento, que ejecutamos la Calculadora) sí, teníamos razón: 99 no es igual a 0 (menos, por supuesto, en las elecciones de la familia del scripting, donde 99 votos del padre del scripting sólo suman 0). Esto es importante, porque aunque se pudo establecer la conexión con el equipo 2, Err no es igual a 0. Y, como Err no es igual a 0, ni siquiera intentamos cambiar la contraseña del administrador local.

Es decir, si cambia el valor de Err, deberá restablecer el valor a 0; de lo contrario, a partir de ese momento, el script creerá que se produjo un error. ¿Y cómo se restablece el valor del objeto Err a 0? Exacto: mediante una llamada a Err.Clear.

A continuación, incrementamos el valor de i en 1. ¿Por qué? La primera vez que pasó por el bucle, la variable i era igual a 2, porque deseábamos establecer la conexión con el equipo que aparecía en la fila 2, columna 1. La segunda vez que pasa por el bucle, lo que deseamos es conectarnos al equipo que aparece en la fila 3, columna 1. Como la variable i indica la fila con la que queremos trabajar, i tiene que ser igual a 3. Y, como todo el mundo sabe, 2+1=3. (Menos mal que todavía se estaba ejecutando la Calculadora.) Sólo entonces usamos el bucle y repetimos el proceso con el siguiente equipo de la hoja de cálculo.

Eso está muy bien pero, como ya no somos tan inocentes como antes, somos conscientes de que este script, por sí mismo, no podrá reducir la cantidad de mensajes de correo electrónico que recibimos. "Eso que hicieron con Excel estaba bien", dirá la gente, "pero tengo que cambiar la contraseña del administrador local en todos los equipos de una unidad organizativa o en todos los equipos que aparecen en un archivo de texto. O quizás me gustaría ver una lista de equipos y poder seleccionar uno de ellos en un cuadro de lista. O quizás lo que querría hacer es..."

Relájese. Sus deseos son órdenes para los chicos del scripting. (Suponiendo que esté dispuesto a esperar cuatro años a que su deseo se cumpla.) En realidad, tenemos muchas plantillas para varios equipos publicadas en Script Center, y estas plantillas facilitan enormemente la ejecución de un script en varios equipos. Por ejemplo, supongamos que desea cambiar la contraseña del administrador local para todos los equipos de una unidad organizativa. No hay problema. La plantilla para ejecutar un script en todos los equipos de una unidad organizativa tiene un aspecto como el presentado en la Figura 4.

Figure 4 Ejecución de un script en una unidad organizativa

On Error Resume Next

Set objOU = GetObject(“LDAP://OU=Finance,dc=fabrikam,dc=com”)
objOU.Filter = Array(“Computer”)

For Each objComputer in objOU
    strComputer = objComputer.CN

    ‘ 
=====================================================================
    ‘ Insert your code here
    ‘ 
=====================================================================

    Set objComputer = GetObject(“WinNT://” & strComputer & “”)
    objComputer.Filter = Array(“User”)
    For Each objUser in objComputer
        Wscript.Echo objUser.Name
    Next

    ‘ 
=====================================================================
    ‘ End
    ‘ 
=====================================================================

Next

¿Ve la sección de la plantilla denominada "Insert your code here" (Inserte el código aquí)? Lo único que debe hacer es eliminar el código de ejemplo de esa sección y reemplazarlo por el código (que puede copiar desde este artículo) para cambiar la contraseña del administrador local. Es decir, reemplace el código de ejemplo por el siguiente código:

Set objUser = GetObject(“WinNT://” & _
    strComputer & “/Administrator”)
If Err = 0 Then
    objUser.SetPassword “egTY634!alK2”
End If
Err.Clear

Este ejemplo en concreto no registrará los resultados, pero puede agregar el código necesario para hacerlo. Reemplace el código de ejemplo, cambie la cadena de conexión LDAP://OU=Finance,dc=fabri­kam,dc=com para dirigirla a una de sus unidades organizativas, y ya está.

En realidad, publicamos estas plantillas hace más de un año, creyendo que serían uno de los elementos más populares de Script Center. Nos equivocábamos: casi nunca se usan, aunque casi cada día la gente nos escribe preguntándonos cómo pueden ejecutar scripts en varios equipos. Damos por supuesto que nadie sabía que estas plantillas existían. Pero ahora ya lo sabe. O lo sabrá si le decimos dónde encontrarlas: microsoft.com/technet/scriptcenter/scripts/templates. Quizás por eso nadie usó nunca estas plantillas...

Ahora que los chicos del scripting ya no son tan inocentes como antes, ¿significa también que no son tan tontos y torpes como antes? Digámoslo así: hace un tiempo, no demasiado, uno de los chicos del scripting decidió pasar el fin de semana arreglando unas cosas en casa. Cuando vino a trabajar el lunes, tenía un pulgar aplastado que no dejaba de sangrar y un gran corte en la pierna.

Si lo pensamos bien, tampoco estaba tan mal. Por lo menos, no para un chico del scripting.

Los chicos del scripting de Microsoft trabajan para (bueno, son empleados de) Microsoft. Cuando no juegan al béisbol, ni entrenan ni lo ven (u otras actividades varias), dirigen 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.