scripting - script - ¿Cómo se ejecuta un comando nativo arbitrario desde una cadena?
programar shell script linux (3)
La respuesta aceptada no me funcionaba cuando intentaba analizar el registro para cadenas de desinstalación y ejecutarlas. Resulta que no necesitaba la llamada a Invoke-Expression
después de todo.
Finalmente encontré esta bonita plantilla para ver cómo ejecutar las cadenas de desinstalación:
$path = ''HKLM:/SOFTWARE/Wow6432Node/Microsoft/Windows/CurrentVersion/Uninstall''
$app = ''MyApp''
$apps= @{}
Get-ChildItem $path |
Where-Object -FilterScript {$_.getvalue(''DisplayName'') -like $app} |
ForEach-Object -process {$apps.Set_Item(
$_.getvalue(''UninstallString''),
$_.getvalue(''DisplayName''))
}
foreach ($uninstall_string in $apps.GetEnumerator()) {
$uninstall_app, $uninstall_arg = $uninstall_string.name.split('' '')
& $uninstall_app $uninstall_arg
}
Esto funciona para mí, principalmente porque $app
es una aplicación interna que sé que solo tendrá dos argumentos. Para cadenas de desinstalación más complejas, es posible que desee utilizar el operador de combinación . Además, acabo de utilizar un hash-map, pero en realidad, probablemente quieras usar una matriz.
Además, si tiene instaladas varias versiones de la misma aplicación, este desinstalador se MsiExec.exe
por todas ellas de una vez, lo que confunde a MsiExec.exe
, por lo que también existe.
Puedo expresar mi necesidad con la siguiente situación: escribir una función que acepte una cadena para ejecutarla como un comando nativo.
No es una idea demasiado exagerada: si está interactuando con otras utilidades de línea de comandos de otra parte de la empresa que le proporciona un comando para ejecutar al pie de la letra. Como no controla el comando, debe aceptar cualquier comando válido como entrada . Estos son los principales contratiempos que no he podido superar fácilmente:
El comando puede ejecutar un programa que viva en un camino con un espacio en él:
$command = ''"C:/Program Files/TheProg/Runit.exe" Hello'';
El comando puede tener parámetros con espacios en ellos:
$command = ''echo "hello world!"'';
El comando puede tener ticks simples o dobles:
$command = "echo `"it`''s`"";
¿Hay alguna forma limpia de lograr esto? Solo he sido capaz de idear soluciones escandalosas y feas, pero para un lenguaje de scripting siento que esto debería ser completamente simple.
También vea este informe de Microsoft Connect básicamente, qué fácil es usar PowerShell para ejecutar comandos de shell (¡oh, la ironía!).
http://connect.microsoft.com/PowerShell/feedback/details/376207/
Sugieren usar --%
como una forma de forzar a PowerShell a dejar de intentar interpretar el texto a la derecha.
Por ejemplo:
MSBuild /t:Publish --% /p:TargetDatabaseName="MyDatabase";TargetConnectionString="Data Source=./;Integrated Security=True" /p:SqlPublishProfilePath="Deploy.publish.xml" Database.sqlproj
Invoke-Expression
, también con alias como iex
. Lo siguiente funcionará en sus ejemplos # 2 y # 3:
iex $command
Algunas cadenas no se ejecutarán como están, como su ejemplo n. ° 1 porque el exe está entre comillas. Esto funcionará como está, porque el contenido de la cadena es exactamente como lo ejecutaría directamente desde el símbolo del sistema de Powershell:
$command = ''C:/somepath/someexe.exe somearg''
iex $command
Sin embargo, si el exe está entre comillas, necesita la ayuda de &
para que se ejecute, como en este ejemplo, como se ejecuta desde la línea de comandos:
>> &"C:/Program Files/Some Product/SomeExe.exe" "C:/some other path/file.ext"
Y luego en el guion:
$command = ''"C:/Program Files/Some Product/SomeExe.exe" "C:/some other path/file.ext"''
iex "& $command"
Probablemente, podría manejar casi todos los casos al detectar si el primer carácter de la cadena de comando es "
, como en esta implementación ingenua:
function myeval($command) {
if ($command[0] -eq ''"'') { iex "& $command" }
else { iex $command }
}
Pero puede encontrar algunos otros casos que deben invocarse de una manera diferente. En ese caso, deberá usar try{}catch{}
, quizás para tipos / mensajes de excepción específicos, o examinar la cadena de comandos.
Si siempre recibe rutas absolutas en lugar de rutas relativas, no debería tener muchos casos especiales, si los hubiera, fuera de los 2 anteriores.