Principales respuestas
Ejecutar .exe con Invoke-Expression

Pregunta
-
Buenos días, mi pregunta se refiere a la sintaxis del cmdlet Invoke-Expression (¿es el usado para ejecutar aplicaciones desde un script?) para la ejecución de un .exe que tiene argumentos y además parte del path está contenido en una variable (por ejemplo $a), es decir de la forma:
Invoke-Expression "$a\<mas path>\ejecutable.exe /p1 /pe"
De esta manera no se me ejecuta, ¿alguna idea? Gracias
Respuestas
-
Si esa ruta incluye espacios, es necesario que incluyas comillas para encerrarla, lo que te obliga a llamar el ejecutable de una manera en la que no es necesario usar Invoke-Expression. Veamos esto que digo.
Si copias el ejecutable del bloc de notas a una carpeta de tu equipo que tenga espacio/s en su ruta y tratas de ejecutarlo con Invoke-Expression te dará error:
PS P:\> Invoke-Expression "C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe"
El término 'C:\Users\Mortadelo\Documents\Documentación' no se reconoce como nombre de un cmdlet, función, archivo de script o programa ejecutable. Compruebe si escribió correctamente el nombre o, si incluyó una ruta de acceso, compruebe que dicha ruta es correcta e inténtelo de nuevo. En línea: 1 Carácter: 43 + C:\Users\05251804F\Documents\Documentación <<<< Microsoft\notepad.exe + CategoryInfo : ObjectNotFound: (C:\Users\052518...s\Documentación:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundExceptionSi le suministras las comillas, es necesario que les quites el significado con acento grave ("`"); en este caso, resulta que lo único que optienes es la devolución en la consola de la ruta montada:
PS P:\> Invoke-Expression "`"C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe`"" C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe
Para que así se ejecute, es necesario que precedas con un ampersand a la ruta del ejecutable:
PS P:\> Invoke-Expression "& `"C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe`""
De esta forma verás cómo sí se abre el bloc de notas. Ahora viene lo bueno...
Si tienes que preceder con el ampersand la ruta, ya no es necesario que utilices una llamada a Invoke-Expression, pues ejecutarás el bloc de notas también así:
PS P:\> & "C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe"
Conclusión, no necesitas Invoke-Expression para lanzar un EXE. Mira, esto también abrirá el bloc de notas:PS P:\> $Notepad = "C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe" PS P:\> & $Notepad
Vamos a complicarlo un poco más, vamos a pasar un fichero como parámetro al bloc de notas para que lo abra. Obseva cómo no hay problema si lo hacemos con el bloc de notas original, que no incluye espacios en su ruta. De esta forma abrimos el fichero b.txt que está en la unidad P:PS P:\> invoke-expression "C:\Windows\System32\notepad.exe p:\b.txt"
Pero en cuanto tengamos espacios, aunque encerremos la ruta entre comillas no funcionará, pues se enreda con los argumentos:PS P:\> invoke-expression "`"C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe`" p:\b.txt" Invoke-Expression : Símbolo (token) inesperado 'p:\b.txt' en la expresión o la instrucción. En línea: 1 Carácter: 18 + invoke-expression <<<< "`"C:\Users\05251804F\Documents\Documentación Microsoft\notepad.exe`" p:\b.txt" + CategoryInfo : ParserError: (p:\b.txt:String) [Invoke-Expression], ParseException + FullyQualifiedErrorId : UnexpectedToken,Microsoft.PowerShell.Commands.InvokeExpressionCommand
Si no usas Invoke-Expression, aparentemente tienes el mismo problema:PS P:\> & "`"C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe`" p:\b.txt" El término '"C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe" p:\b.txt' no se reconoce como
nombre de un cmdlet, función, archivo de script o programa ejecutable. Compruebe si escribió correctamente el nombre
o, si incluyó una ruta de acceso, compruebe que dicha ruta es correcta e inténtelo de nuevo. En línea: 1 Carácter: 2 + & <<<< "`"C:\Users\05251804F\Documents\Documentación Microsoft\notepad.exe`" p:\b.txt" + CategoryInfo : ObjectNotFound: ("C:\Users\05251...d.exe" p:\b.txt:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundExceptionEsto es debido a que tienes que separar los argumentos del ejecutable y entre ellos; de esta otra forma sí funcionará:
PS P:\> & "C:\Users\05251804F\Documents\Documentación Microsoft\notepad.exe" p:\b.txt
Es decir, que la sintaxis es:& <ejecutable> <argumento1> <argumento2> ... <argumentoN>
Por supuesto, cada uno de estos elementos, si es necesario puede ir entre comillas. Pongamos como ejemplo que el ejecutable con la ruta en la que hay espacio/s tenga que abrir un fichero que esté en la misma ruta que él (para mayor claridad he separado la línea de invocación en dos, con el caracter continuador de línea, el acento grave, para que así PowerShell lo considere una misma línea):
PS P:\> & "C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe" ` >> "C:\Users\Mortadelo\Documents\Documentación De Disfraces\rana.txt" >>
Esto sí funcionará.
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/
freyes.champú@champú.mvps.org
(Aclárate la cabeza si quieres escribirme)
- Editado Fernando ReyesModerator lunes, 6 de febrero de 2012 8:30
- Marcado como respuesta Miguel A. Abarca lunes, 6 de febrero de 2012 12:40
-
Sí, esa sería la forma. Te lo voy a complicar un poco más para ver si así resuelvo todas las dudas.
Vamos a cambiar de aplicación de ejemplo, vamos a poner msinfo32.exe, para así poder complicar el tema de los parámetros. Al igual que hicimos con notepad.exe, copiaremos el ejecutable a una carpeta con espacio/s en su ruta.
En el ejemplo volcaremos la información del sistema a un fichero txt. Si miras la sintaxis de línea de comandos de msinfo32.exe, desde un cmd.exe ejecutaríamos:
msinfo32.exe /report fichero.txt /categories +systemsummary
Cuando esto lo llevamos a PowerShell, cada espacio que separa "cosas" deberemos escribirlo también y encerrar entre comillas las "cosas" que lleven espacios. Si seguimos con los ejemplos anteriores, esta línea la podríamos lanzar así:PS P:\> & "C:\Users\Mortadelo\Documents\Documentación De Disfraces\msinfo32.exe" ` >> /Report "C:\Users\Mortadelo\Documents\Documentación De Disfraces\systemsummary.txt" ` >> /categories +systemsummary >>
Supón que los parámetros con nombre son esos en los que que el dato se separa de la etiqueta por dos puntos (como VbScript) y no por un espacio, como hemos visto ahora mismo; en ese caso tanto el dato como la etiqueta deberán ir juntos (/etiqueta:dato), si el dato tiene espacio/s deberá ser encerrado entre comillas a las que se haya quitado el significado (/etiqueta:`"dato con espacio/s`"), e incluso si la etiqueta también tiene espacio/s (sí, raro, pero VbScript, por ejemplo, permite parámetros con nombre que tengan espacio/s en el nombre) también ésta deberá encerrarse entre comillas con el significado quitado (/`"Con Espacio`":`"Valor con espacios`"). Esto último, para descreídos, puedes comprobarlo de la siguiente manera:Creamos en la carpeta en la que estamos realizando las pruebas un script VbScript de nombre Con Espacio.vbs. El contenido de este script será tan sólo esta línea:
WScript.Echo WScript.Arguments.Named("Con Espacio")
Es decir, que lo único que hace es mostrar el contenido del dato que se haya pasado como parámetro de nombre Con Espacio. Si invocásemos este script desde una ventana de comandos haríamos así:
cscript //nologo "C:\Users\Mortadelo\Documents\Documentación De Disfraces\Con Espacio.vbs" /"Con Espacio":"Valor con espacios"
Pues bien, esta misma invocación, desde PowerShell sería:PS P:\> & cscript //nologo "C:\Users\Mortadelo\Documents\Documentación De Disfraces\Con Espacio.vbs" ` /`"Con Espacio`":`"Valor con espacios`"
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/
freyes.champú@champú.mvps.org
(Aclárate la cabeza si quieres escribirme)- Marcado como respuesta Miguel A. Abarca miércoles, 8 de febrero de 2012 7:51
Todas las respuestas
-
Si esa ruta incluye espacios, es necesario que incluyas comillas para encerrarla, lo que te obliga a llamar el ejecutable de una manera en la que no es necesario usar Invoke-Expression. Veamos esto que digo.
Si copias el ejecutable del bloc de notas a una carpeta de tu equipo que tenga espacio/s en su ruta y tratas de ejecutarlo con Invoke-Expression te dará error:
PS P:\> Invoke-Expression "C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe"
El término 'C:\Users\Mortadelo\Documents\Documentación' no se reconoce como nombre de un cmdlet, función, archivo de script o programa ejecutable. Compruebe si escribió correctamente el nombre o, si incluyó una ruta de acceso, compruebe que dicha ruta es correcta e inténtelo de nuevo. En línea: 1 Carácter: 43 + C:\Users\05251804F\Documents\Documentación <<<< Microsoft\notepad.exe + CategoryInfo : ObjectNotFound: (C:\Users\052518...s\Documentación:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundExceptionSi le suministras las comillas, es necesario que les quites el significado con acento grave ("`"); en este caso, resulta que lo único que optienes es la devolución en la consola de la ruta montada:
PS P:\> Invoke-Expression "`"C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe`"" C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe
Para que así se ejecute, es necesario que precedas con un ampersand a la ruta del ejecutable:
PS P:\> Invoke-Expression "& `"C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe`""
De esta forma verás cómo sí se abre el bloc de notas. Ahora viene lo bueno...
Si tienes que preceder con el ampersand la ruta, ya no es necesario que utilices una llamada a Invoke-Expression, pues ejecutarás el bloc de notas también así:
PS P:\> & "C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe"
Conclusión, no necesitas Invoke-Expression para lanzar un EXE. Mira, esto también abrirá el bloc de notas:PS P:\> $Notepad = "C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe" PS P:\> & $Notepad
Vamos a complicarlo un poco más, vamos a pasar un fichero como parámetro al bloc de notas para que lo abra. Obseva cómo no hay problema si lo hacemos con el bloc de notas original, que no incluye espacios en su ruta. De esta forma abrimos el fichero b.txt que está en la unidad P:PS P:\> invoke-expression "C:\Windows\System32\notepad.exe p:\b.txt"
Pero en cuanto tengamos espacios, aunque encerremos la ruta entre comillas no funcionará, pues se enreda con los argumentos:PS P:\> invoke-expression "`"C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe`" p:\b.txt" Invoke-Expression : Símbolo (token) inesperado 'p:\b.txt' en la expresión o la instrucción. En línea: 1 Carácter: 18 + invoke-expression <<<< "`"C:\Users\05251804F\Documents\Documentación Microsoft\notepad.exe`" p:\b.txt" + CategoryInfo : ParserError: (p:\b.txt:String) [Invoke-Expression], ParseException + FullyQualifiedErrorId : UnexpectedToken,Microsoft.PowerShell.Commands.InvokeExpressionCommand
Si no usas Invoke-Expression, aparentemente tienes el mismo problema:PS P:\> & "`"C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe`" p:\b.txt" El término '"C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe" p:\b.txt' no se reconoce como
nombre de un cmdlet, función, archivo de script o programa ejecutable. Compruebe si escribió correctamente el nombre
o, si incluyó una ruta de acceso, compruebe que dicha ruta es correcta e inténtelo de nuevo. En línea: 1 Carácter: 2 + & <<<< "`"C:\Users\05251804F\Documents\Documentación Microsoft\notepad.exe`" p:\b.txt" + CategoryInfo : ObjectNotFound: ("C:\Users\05251...d.exe" p:\b.txt:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundExceptionEsto es debido a que tienes que separar los argumentos del ejecutable y entre ellos; de esta otra forma sí funcionará:
PS P:\> & "C:\Users\05251804F\Documents\Documentación Microsoft\notepad.exe" p:\b.txt
Es decir, que la sintaxis es:& <ejecutable> <argumento1> <argumento2> ... <argumentoN>
Por supuesto, cada uno de estos elementos, si es necesario puede ir entre comillas. Pongamos como ejemplo que el ejecutable con la ruta en la que hay espacio/s tenga que abrir un fichero que esté en la misma ruta que él (para mayor claridad he separado la línea de invocación en dos, con el caracter continuador de línea, el acento grave, para que así PowerShell lo considere una misma línea):
PS P:\> & "C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe" ` >> "C:\Users\Mortadelo\Documents\Documentación De Disfraces\rana.txt" >>
Esto sí funcionará.
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/
freyes.champú@champú.mvps.org
(Aclárate la cabeza si quieres escribirme)
- Editado Fernando ReyesModerator lunes, 6 de febrero de 2012 8:30
- Marcado como respuesta Miguel A. Abarca lunes, 6 de febrero de 2012 12:40
-
Muchas gracias por tu exausta respuesta, sólo me ha quedado una pequeña duda: por ejemplo en el caso que propones si la aplicación aceptara más de un parámetro, ¿funcionaría de esta manera:?
PS P:\> & "C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe" /p1 /p2
-
Sí, esa sería la forma. Te lo voy a complicar un poco más para ver si así resuelvo todas las dudas.
Vamos a cambiar de aplicación de ejemplo, vamos a poner msinfo32.exe, para así poder complicar el tema de los parámetros. Al igual que hicimos con notepad.exe, copiaremos el ejecutable a una carpeta con espacio/s en su ruta.
En el ejemplo volcaremos la información del sistema a un fichero txt. Si miras la sintaxis de línea de comandos de msinfo32.exe, desde un cmd.exe ejecutaríamos:
msinfo32.exe /report fichero.txt /categories +systemsummary
Cuando esto lo llevamos a PowerShell, cada espacio que separa "cosas" deberemos escribirlo también y encerrar entre comillas las "cosas" que lleven espacios. Si seguimos con los ejemplos anteriores, esta línea la podríamos lanzar así:PS P:\> & "C:\Users\Mortadelo\Documents\Documentación De Disfraces\msinfo32.exe" ` >> /Report "C:\Users\Mortadelo\Documents\Documentación De Disfraces\systemsummary.txt" ` >> /categories +systemsummary >>
Supón que los parámetros con nombre son esos en los que que el dato se separa de la etiqueta por dos puntos (como VbScript) y no por un espacio, como hemos visto ahora mismo; en ese caso tanto el dato como la etiqueta deberán ir juntos (/etiqueta:dato), si el dato tiene espacio/s deberá ser encerrado entre comillas a las que se haya quitado el significado (/etiqueta:`"dato con espacio/s`"), e incluso si la etiqueta también tiene espacio/s (sí, raro, pero VbScript, por ejemplo, permite parámetros con nombre que tengan espacio/s en el nombre) también ésta deberá encerrarse entre comillas con el significado quitado (/`"Con Espacio`":`"Valor con espacios`"). Esto último, para descreídos, puedes comprobarlo de la siguiente manera:Creamos en la carpeta en la que estamos realizando las pruebas un script VbScript de nombre Con Espacio.vbs. El contenido de este script será tan sólo esta línea:
WScript.Echo WScript.Arguments.Named("Con Espacio")
Es decir, que lo único que hace es mostrar el contenido del dato que se haya pasado como parámetro de nombre Con Espacio. Si invocásemos este script desde una ventana de comandos haríamos así:
cscript //nologo "C:\Users\Mortadelo\Documents\Documentación De Disfraces\Con Espacio.vbs" /"Con Espacio":"Valor con espacios"
Pues bien, esta misma invocación, desde PowerShell sería:PS P:\> & cscript //nologo "C:\Users\Mortadelo\Documents\Documentación De Disfraces\Con Espacio.vbs" ` /`"Con Espacio`":`"Valor con espacios`"
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/
freyes.champú@champú.mvps.org
(Aclárate la cabeza si quieres escribirme)- Marcado como respuesta Miguel A. Abarca miércoles, 8 de febrero de 2012 7:51
-
-
Muchas gracias por tu exausta respuesta, sólo me ha quedado una pequeña duda: por ejemplo en el caso que propones si la aplicación aceptara más de un parámetro, ¿funcionaría de esta manera:?
PS P:\> & "C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe" /p1 /p2
Pues aunque parezca íncomprensible a mí no me funcionó hasta que no enlacé esa línea con otro cmdlet:
Así NO me funciona:
PS P:\> & "C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe" /p1 /p2
Así SÍ me funciona:
PS P:\> & "C:\Users\Mortadelo\Documents\Documentación De Disfraces\notepad.exe" /p1 /p2 `
| Out-File -FilePath <logfile> -Append
Extraño, ¿no?
-
¿Puedes poner en concreto qué estás intentando ejecutar, a ver si hay algo que se nos escapa? Con el ejemplo del notepad no hacemos nada.
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/
freyes.champú@champú.mvps.org
(Aclárate la cabeza si quieres escribirme) -
Se trata de instalar una aplicación si no lo está ya y unos cuantos plugins. La ruta comun a todo es:
$rutaComun = " <a href="file://\\\sdlibrary$\<carpeta1>"">\\<server>\sdlibrary$\<carpeta1>"
El ejecutable principal se encuentra en la ruta:
"$rutaComun\<carpeta2>\ejecutable.exe"
Y con
& "$rutaComun\<carpeta2>\ejecutable.exe" /p1 /p2
NO pita, sin embargo añadiendo una tubería SÍ
& "$rutaComun\<carpeta2>\ejecutable.exe" /p1 /p2 | Out-Null
-
Tal y como lo pones $RutaComun es muy raro, si se trata de una cadena, debería ser:
$rutaComun = " <a href=`"file://\\\sdlibrary`$\<carpeta1>`">\\<server>\sdlibrary`$\<carpeta1>"
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/
freyes.champú@champú.mvps.org
(Aclárate la cabeza si quieres escribirme)
- Editado Fernando ReyesModerator jueves, 9 de febrero de 2012 15:25
-
Aunque supongio que en realidad se te ha debido poner alguna "guarrería" con el copy/paste y en realidad querías poner:
$rutaComun = "\\<server>\sdlibrary$\<carpeta1>"
En ese caso, puede que te esté dando problemas el dolar, al que se debería quitar el significado con acento grave:
$rutaComun = "\\<server>\sdlibrary`$\<carpeta1>"
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/
freyes.champú@champú.mvps.org
(Aclárate la cabeza si quieres escribirme) -
Hola de nuevo y disculpa mi retraso, he estado ausente unos días.
Efectivamente el copy/paste salió mal y quería decir exactamente lo que comentas en tu última respuesta.
No hay problema con el signo $ si no no se ejecutaría en ningún caso, ¿no? De todas formas lo he comprobado por si acaso y no rula tampoco sin entubar la ejecución aunque sea a un Out-Null.
-
No lo entiendo ¿Si encierras entre comillas los /Pn tampoco funciona?
& "$rutaComun\<carpeta2>\ejecutable.exe" "/p1" "/p2"
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/
freyes.champú@champú.mvps.org
(Aclárate la cabeza si quieres escribirme) -
-
Pues qué rarito... :oO
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/
freyes.champú@champú.mvps.org
(Aclárate la cabeza si quieres escribirme)