¿Cómo escapar de caracteres especiales en PowerShell?
Cuando se ejecuta mi script de PowerShell, le solicita al usuario un parámetro de contraseña. Esa contraseña puede contener cualquier cantidad de caracteres especiales como *\~;(%?.:@/ Esa contraseña luego se usa como parámetro para un comando .exe, pero a menudo es incorrecta debido a que algunos caracteres especiales no se escapan correctamente.
Un ejemplo de contraseña anterior era $(?-.?-(. Los únicos caracteres que necesitaba para escapar eran '(', que reemplacé con '`(' para que funcionara. Sin embargo, esa contraseña ya expiró. La nueva contraseña es algo así como *\~;~(%?.:@/ *NOTA: estas contraseñas también tienen números y letras aleatorios mezclados, pero han sido redactadas.
Los únicos caracteres de la nueva contraseña que NO están en el primero son *\~;%:@/ ¿Existe una manera fácil de escapar de todos los caracteres y simplemente tomar cualquier entrada del usuario tal como está? Si no, ¿a alguien le importaría ayudarme a escapar de estos personajes especiales?
param (
[Parameter(Mandatory=$true)][string]$password
)
El código anterior precede al script, lo que hace que la consola solicite la entrada del usuario.
Invoke-Expression -Command "<path_to_exe> -install $user $password"
^este es el comando que usa ese parámetro de contraseña
Probé muchas otras sugerencias en Stack Overflow, Reddit y otros foros/blogs de codificación y ninguna funcionó. ¡Cualquier ayuda es muy apreciada!
Estás usando Invoke-Expression
para llamar a un programa externo :
No hay razón para hacerlo y,
Invoke-Expression
en general, debe evitarse : causa dolores de cabeza (como en su caso), pero, lo que es más importante, puede ser un riesgo para la seguridad y, por lo general, existen mejores soluciones.- Como comentario aparte: desafortunadamente, incluso con la invocación directa puede haber desafíos al citar argumentos de cadena vacía y argumentos con caracteres incrustados
"
. - consulte la nota al pie [1] y esta respuesta .
- Como comentario aparte: desafortunadamente, incluso con la invocación directa puede haber desafíos al citar argumentos de cadena vacía y argumentos con caracteres incrustados
Si, en cambio, invoca el programa externo directamente , como está diseñado para hacer cualquier shell, incluido PowerShell, es probable que su problema desaparezca : [1]
& <path_to_exe> -install $user $password
Nota: , el operador de llamada&
de PowerShell , solo es necesario si la ruta de su ejecutable está citada (por ejemplo, ) y/o se especifica mediante una referencia variable (por ejemplo, ); de lo contrario, puede invocar el ejecutable tal cual (por ejemplo, para invocar , use algo como )."C:\Program Files\foo.exe"
$HOME\foo.exe
cmd.exe
cmd /c 'echo hi'
Por separado, si alguna vez necesita escapar de cualquiera de los caracteres de un conjunto de caracteres, utilícelo -replace
con una clase de carácter ,[...]
:
Nota : Esto no es necesario para pasar argumentos, ni a programas externos, como se muestra arriba, ni a comandos de PowerShell; sin embargo, debido al manejo incorrecto de PowerShell de "
los caracteres incrustados en los valores de los argumentos pasados a programas externos , es posible que tenga que utilizar "
caracteres de escape (únicamente), como \"
[1] .
PS> 'a*b\c~d;e(f%g?h.i:j@k/l' -replace '[*\\~;(%?.:@/]', '`$&'
a`*b`\c`~d`;e`(f`%g`?h`.i`:j`@k`/l # all chars. inside [...] were `-escaped
Nota: Dado que \
tiene un significado especial incluso dentro de una clase de carácter, debía escaparse como \\
todos los demás caracteres. se utilizan tal cual.
Para obtener más información sobre el -replace
operador, consulte esta respuesta .
[1] Hay un carácter que todavía causa problemas: incrustado "
. Por razones históricas, PowerShell no pasa correctamente la integración "
a programas externos y, molestamente, requiere escape manual en las versiones de Windows PowerShell y PowerShell (Core) hasta v7.2.x; consulte esta respuesta para obtener más detalles. Aplicado a su solución :)\
& <path_to_exe> -install $user ($password -replace '"', '\"'
El uso de lo siguiente escapará de los caracteres usando el prefijo de escape que mencionaste. El prefijo de escape normal es \ como se muestra a continuación. Lo configuré de esta manera para que le resulte más fácil agregar caracteres adicionales para escapar o cambiar el prefijo de escape.
function Set-EscapeCharacters {
Param(
[parameter(Mandatory = $true, Position = 0)]
[String]
$string
)
$string = $string -replace '\*', '`*'
$string = $string -replace '\\', '`\'
$string = $string -replace '\~', '`~'
$string = $string -replace '\;', '`;'
$string = $string -replace '\(', '`('
$string = $string -replace '\%', '`%'
$string = $string -replace '\?', '`?'
$string = $string -replace '\.', '`.'
$string = $string -replace '\:', '`:'
$string = $string -replace '\@', '`@'
$string = $string -replace '\/', '`/'
$string
}
$Password = Set-EscapeCharacters $Password