none
Problema con ejecución remota via WMI. RRS feed

  • Pregunta

  • Hola,

    Estoy utilizando el código que creó Fernando Reyes en su blog para ejecutar comandos remotos mediante WMI con credenciales, utilizando el método Create de WIN32_Process.

    En general, me funciona correctamente, pero tengo un problema con algunos servidores Windows 2000. Ocurre una cosa muy rara: en algunos servidores, no en todos, intento ejecutar un script y el proceso me devuelve el código 8 (Error desconocido). Si inicio sesión en el servidor, ejecuto el script localmente, y salgo del servidor, a partir de ese momento, ya me funciona correctamente la ejecución remota con la llamada WMI.

    Me he vuelto medio tonto buscando una solución o el motivo por el que esto ocurre, y no encuentro nada, así que tengo que aplicar otra solución.

    La única manera que conozco de ejecutar comandos remotos con vbs es utilizando el método run de la clase WScript.Shell y hacer una llamada remota mediante PSEXEC.

    De esta forma, funciona perfectamente, pero tengo un problema: no sé cómo verificar que, efectivamente, se ha ejecutado el comando correctamente. Visualmente lo puedo comprobar, porque si ejecuto el método RUN con el parámetro 1, tengo la ventana a la vista y si no va muy rápido el error, puedo llegar a ver si se ha ejecutado correctamente o no, pero el script vbs no tiene manera de saberlo, y yo necesito que el script sepa si se ha ejecutado correctamente el comando remoto o no.

    ¿Sabéis cómo puedo gestionar esto? ¿Alguna manera de ejecutar el comando remoto que pueda saber si se ha ejecutado correctamente o no, y que no sea con la llamada a Win32_Process? ¿Alguna pista de por qué ocurre ese comportamiento en algunos servidores?

    Gracias

    lunes, 17 de junio de 2013 15:57

Respuestas

  • Podrías hacerlo con un bat:

    comando = "PSEXEC.EXE \\Equipo -u usuario -p contraseña cmd /c \\servidor\carpeta\fichero.bat"


    Un saludo

    Fernando Reyes [MS MVP]
    MCSA 2000/2003
    MCSE 2000/2003
    MCITP EnterpriseAdministrator
    Web: http://freyes.svetlian.com
    Blog: http://urpiano.wordpress.com
    RSS: http://urpiano.wordpress.com/feed/

    • Marcado como respuesta Paco Gaspar martes, 18 de junio de 2013 16:03
    martes, 18 de junio de 2013 14:06
    Moderador
  • Bueno, Fernando me puso sobre la pista con esos enlaces. La solución es algo chapucera, pero funciona.

    Antes de lanzar el process.create, consulto si existe la carpeta del perfil del usuario que ejecutará la instrucción. Si existe, lanza el proceso y se ejecuta correctamente. Si no existe, creo una carpeta con el nombre del usuario en C:\Documents and Settings, y copio en ella el fichero ntuser.dat del default user. Después, lanzo el proceso y funciona correctamente.

    En esos servidores, los perfiles locales se eliminan dos veces por semana. Si no existe el perfil del usuario con el que se lanza la conexión wmi, el process.create genera el error 8.

    Gracias por las respuestas.

    miércoles, 19 de junio de 2013 12:49

Todas las respuestas

  • ¿Por qué no usas un bat y PSEXEC directamente si estás ejecutando comandos en el servidor remoto?

    De todas formas, a ver si algo de esto te puede ayudar:

    http://computer-programming-forum.com/61-wsh/77649c05d64c0d3f.htm

    http://blogs.msdn.com/b/alejacma/archive/2008/04/09/win32-process-create-fails-if-user-profile-is-not-loaded.aspx?Redirected=true

    http://social.technet.microsoft.com/Forums/en-US/winserverManagement/thread/305557c4-df94-4d92-85bf-a049c83f120c


    Un saludo

    Fernando Reyes [MS MVP]
    MCSA 2000/2003
    MCSE 2000/2003
    MCITP EnterpriseAdministrator
    Web: http://freyes.svetlian.com
    Blog: http://urpiano.wordpress.com
    RSS: http://urpiano.wordpress.com/feed/

    martes, 18 de junio de 2013 8:47
    Moderador
  • No ejecuto un bat porque todo el proceso forma parte de una aplicación en vbs y hta. Hay un montón de tareas automatizadas que se gestionan mediante scripts, en vbs, y me han hecho ponerlas todas juntas en una aplicación con interfaz de usuario, para lo que he empleado HTA.

    Algunas de esas acciones, requieren ejecución remota de scripts o de comandos. Y por alguna razón que desconozco, en algunos servidores Windows 2000 no funciona. Voy a mirar los enlaces que me pones. El problema del PSEXEC es que no tengo forma de que el script capture si se ha ejecutado con éxito o no (o al menos yo no sé cómo hacerlo)

    Gracias

    martes, 18 de junio de 2013 11:15
  • Puedes identificar si se ha ejecutado con éxito así:

    VERIFY > nul
    PSEXEC \\EQUIPO -u usuario -p contraseña comando parametros > nul
    IF %ERRORLEVEL% EQU 0 (
        ECHO Equipo: Correcto
    ) ELSE (
        ECHO Equipo: Error %ERRORLEVEL%
    )

    En este caso se muestra un mensaje por pantalla, pero se podría guardar en un fichero temporal y que el vbs lo leyera después de la ejecución para saber el resultado, algo así:

    VERIFY > nul
    PSEXEC \\EQUIPO -u usuario -p contraseña comando parametros > nul
    IF %ERRORLEVEL% EQU 0 (
        ECHO Equipo: Correcto > "%temp%\temp.txt"
    ) ELSE (
        ECHO Equipo: Error %ERRORLEVEL% > "%temp%\temp.txt"
    )


    Un saludo

    Fernando Reyes [MS MVP]
    MCSA 2000/2003
    MCSE 2000/2003
    MCITP EnterpriseAdministrator
    Web: http://freyes.svetlian.com
    Blog: http://urpiano.wordpress.com
    RSS: http://urpiano.wordpress.com/feed/

    martes, 18 de junio de 2013 12:23
    Moderador
  • Gracias Fernando.

    Pero tengo que dar otra vuelta de tuerca. Yo ejecuto el psexec desde dentro del vbs tal que así:

    comando = "PSEXEC.EXE \\Equipo -u usuario -p contraseña comando parametros"

    Set objejecuta = createobject("Wscript.Shell")

    objejecuta.run comando, 0, true

    ¿Cómo puedo incluir todo el código que has puesto ahí para que lo ejecute el vbs?

    martes, 18 de junio de 2013 12:30
  • Podrías hacerlo con un bat:

    comando = "PSEXEC.EXE \\Equipo -u usuario -p contraseña cmd /c \\servidor\carpeta\fichero.bat"


    Un saludo

    Fernando Reyes [MS MVP]
    MCSA 2000/2003
    MCSE 2000/2003
    MCITP EnterpriseAdministrator
    Web: http://freyes.svetlian.com
    Blog: http://urpiano.wordpress.com
    RSS: http://urpiano.wordpress.com/feed/

    • Marcado como respuesta Paco Gaspar martes, 18 de junio de 2013 16:03
    martes, 18 de junio de 2013 14:06
    Moderador
  • Gracias Fernando. ¿Eso no sería una pescadilla que se muerde la cola? Si entiendo bien, el fichero.bat tendría que tener dentro:

    VERIFY > nul
    PSEXEC \\EQUIPO -u usuario -p contraseña comando parametros > nul
    IF %ERRORLEVEL% EQU 0 (
        ECHO Equipo: Correcto > "%temp%\temp.txt"
    ) ELSE (
        ECHO Equipo: Error %ERRORLEVEL% > "%temp%\temp.txt"
    )

    Entonces, mi script vbs llamaría a \\Equipo -u usuario -p contraseña para ejecutar el fichero.bat en \\servidor, que, a su vez, ejecutaría el psexec que llamaría a \\Equipo y que escribiría en %temp% un fichero txt que después podría consultar desde vbs para ver si ha habido error o no. Y ¿Cómo compruebo que la llamada a \\equipo -u usuario -p contraseña cmd /c se ha ejecutado correctamente?

    Lo que sí se me ocurre que puedo intentar hacer es generar en tiempo de ejecución desde vbs un fichero en local, c:\fichero.bat que incluya el código anterior completo y llamar a ese bat con el método run. Consultar el fichero local txt y comprobar si ha habido error o no, y cuando termine, eliminar tanto el bat como el txt con el código de salida.

    Un poco de complicación porque son muchos y diferentes los bat locales con los diferentes comandos psexec, pero creo que esa va a ser la única solución.

    Gracias por la idea :-)

    martes, 18 de junio de 2013 14:33
  • Hay una opción (-c) en PSEXEC que sube el fichero a ejecutar al equipo remoto.

    Un saludo

    Fernando Reyes [MS MVP]
    MCSA 2000/2003
    MCSE 2000/2003
    MCITP EnterpriseAdministrator
    Web: http://freyes.svetlian.com
    Blog: http://urpiano.wordpress.com
    RSS: http://urpiano.wordpress.com/feed/

    martes, 18 de junio de 2013 15:50
    Moderador
  • ¿Y si con "valor=objejecuta.run comando, 0, true" obtienes en valor el código de salida de la ejecución? Ya que el tercer parámetro es "true", de modo que el script espera a que termine el programa ejecutado.

    No puedo garantizar a priori que mis respuestas sean exactas y acordes a los problemas descritos, pero por lo menos yo no las voy marcando como propuestas o definitivas sin saber si han sido útiles o no. Tampoco vinculado a Microsoft.


    • Editado Ramón Sola martes, 18 de junio de 2013 23:47 ANTES PODÍA DEJAR EL MOTIVO EN BLANCO
    martes, 18 de junio de 2013 23:46
  • Gracias Ramón,

    Hasta donde yo sé, el valor que devuelve lo que dices informará de ejecución correcta siempre que el comando PSEXEC llegue a ejecutarse. Si el script remoto que se ejecuta da un error, el valor devuelto será el mismo que si no lo da, ya que de todos modos se habrá ejecutado el psexec. Ese valor solo informará de error en caso de que no llegue a ejecutarse (supongo que por ejemplo, por un problema de comunicaciones, o de credenciales, generaría un código de error). Pero si el script remoto se llega a ejecutar, aunque dé un error, el valor devuelto por el método run será el mismo que si no da error.

    Saludos

    miércoles, 19 de junio de 2013 7:36
  • Bueno, Fernando me puso sobre la pista con esos enlaces. La solución es algo chapucera, pero funciona.

    Antes de lanzar el process.create, consulto si existe la carpeta del perfil del usuario que ejecutará la instrucción. Si existe, lanza el proceso y se ejecuta correctamente. Si no existe, creo una carpeta con el nombre del usuario en C:\Documents and Settings, y copio en ella el fichero ntuser.dat del default user. Después, lanzo el proceso y funciona correctamente.

    En esos servidores, los perfiles locales se eliminan dos veces por semana. Si no existe el perfil del usuario con el que se lanza la conexión wmi, el process.create genera el error 8.

    Gracias por las respuestas.

    miércoles, 19 de junio de 2013 12:49
  • !!Buena solución¡¡ Gracias por compartirla

    Un saludo

    Fernando Reyes [MS MVP]
    MCSA 2000/2003
    MCSE 2000/2003
    MCITP EnterpriseAdministrator
    Web: http://freyes.svetlian.com
    Blog: http://urpiano.wordpress.com
    RSS: http://urpiano.wordpress.com/feed/

    jueves, 20 de junio de 2013 7:36
    Moderador
  • He encontrado otra mejor. Basta con crear la carpeta en C:\Documents and Settings. No hace falta copiar el fichero NTUSER.DAT del Default User para que funcione. Con que exista la carpeta ya funciona.

    Sería de lo más interesante saber por qué ese método necesita que exista esa carpeta. Y más interesante sería saber por qué lo han implementado así, porque es una cagada monumental.

    :-)

    jueves, 20 de junio de 2013 8:32
  • Porque se apoya en el perfil de usuario, digo yo...

    Un saludo

    Fernando Reyes [MS MVP]
    MCSA 2000/2003
    MCSE 2000/2003
    MCITP EnterpriseAdministrator
    Web: http://freyes.svetlian.com
    Blog: http://urpiano.wordpress.com
    RSS: http://urpiano.wordpress.com/feed/

    jueves, 20 de junio de 2013 10:01
    Moderador
  • Si se apoyara en el perfil de usuario, lo entendería y todo, pero no es así: el perfil de usuario está en NTUSER.DAT, no en que exista una carpeta en Documents and settings con el mismo nombre que el usuario.

    Misterios insondables del dios Microsoft :-)

    jueves, 20 de junio de 2013 10:23
  • No, eso no es así Paco, NTUSER.DAT es la rama de registro correspondiente al usuario, pero el perfil está en la carpeta, NTUSER.DAT es una parte más (¡¡y qué parte, nada menos que HKEY_CURRENTUSER!!), pero no es el perfil en sí.

    Un saludo

    Fernando Reyes [MS MVP]
    MCSA 2000/2003
    MCSE 2000/2003
    MCITP EnterpriseAdministrator
    Web: http://freyes.svetlian.com
    Blog: http://urpiano.wordpress.com
    RSS: http://urpiano.wordpress.com/feed/

    viernes, 21 de junio de 2013 6:30
    Moderador
  • Ya lo sé, Fernando, que es la rama del registro que mencionas. Y que eso solo es una parte del perfil. Hay otras cosas más que también forman el perfil.

    Pero lo que desde luego, es, en mi opinión, la parte menos importante del perfil, es la carpeta que lo contiene. Y resulta que para que funcione la llamada remota, la única parte del perfil que es necesario que exista, es la carpeta que contiene al perfil, no el perfil en sí (ni la rama del registro del CurrentUser, ni todo lo demás que, en conjunto, conforma el perfil de un usuario).

    Lo dicho, misterios insondables :-)

    viernes, 21 de junio de 2013 6:36