Как избежать специальных символов в PowerShell?
Когда мой сценарий PowerShell запускается, он запрашивает у пользователя параметр пароля. Этот пароль может содержать любое количество специальных символов, например *\~;(%?.:@/ Этот пароль затем используется в качестве параметра для команды.exe, но часто он неверен из-за того, что некоторые специальные символы не экранируются должным образом.
Примером прошлого пароля был $(?-.?-(. Единственными символами, которые мне нужно было экранировать, были '(', который я заменил на '' (', чтобы он работал. Однако срок действия этого пароля истек. Новый пароль это что-то вроде *\~;~(%?.:@/ * ПРИМЕЧАНИЕ: в этих паролях также смешаны случайные числа и буквы, но они были отредактированы.
Единственные символы в новом пароле, НЕ в первом, - это *\~;%:@/ Есть ли простой способ избежать всех символов и просто принять любой ввод пользователя? Если нет, не мог бы кто-нибудь помочь мне избежать этих специальных символов?
param (
[Parameter(Mandatory=$true)][string]$password
)
Приведенный выше код предшествует сценарию, заставляя консоль запрашивать ввод данных пользователем.
Invoke-Expression -Command "<path_to_exe> -install $user $password"
^ это команда, которая использует этот параметр пароля
Я пробовал много других предложений на stackru, Reddit и других форумах / блогах по кодированию, но ни один из них не сработал. Любая помощь высоко ценится!
2 ответа
Вы используете Invoke-Expression
для вызова внешней программы:
Там нет нет причин, чтобы сделать это, и
Invoke-Expression
обычно следует избегать: это вызывает головную боль при цитировании (как в вашем случае), но, что более важно, это может быть угрозой безопасности, и, как правило, есть лучшие решения.- В качестве отступления: к сожалению, даже при прямом вызове могут возникнуть проблемы с цитированием аргументов с пустой строкой и аргументов со встроенными
"
символы. - см. сноску [1] и этот ответ.
- В качестве отступления: к сожалению, даже при прямом вызове могут возникнуть проблемы с цитированием аргументов с пустой строкой и аргументов со встроенными
Если вместо этого вы вызываете внешнюю программу напрямую - как и предназначена любая оболочка, включая PowerShell, - ваша проблема, скорее всего, исчезнет:[1]
& <path_to_exe> -install $user $password
Примечание: &
, Оператор вызова PowerShell, необходим только в том случае, если путь к вашему исполняемому файлу указан (например,"C:\Program Files\foo.exe"
) и / или указывается через ссылку на переменную (например,$HOME\foo.exe
); в противном случае вы можете вызвать исполняемый файл как есть (например, чтобы вызватьcmd.exe
, используйте что-нибудь вроде cmd /c 'echo hi'
).
Отдельно, если вам когда-нибудь понадобится экранировать любой из символов в наборе символов, используйте-replace
с классом персонажа,[...]
:
Примечание. В этом нет необходимости для передачи аргументов ни во внешние программы, как показано выше, ни в команды PowerShell; однако из-за нарушенной обработки PowerShell"
символы, встроенные в значения аргументов, передаваемых во внешние программы, возможно, вам придется экранировать"
символы (только), как \"
[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
Примечание. Поскольку \
имеет особое значение даже внутри класса символов, его нужно было экранировать как \\
- все остальные символы. используются как есть.
Для получения дополнительной информации о -replace
оператор, см. этот ответ.
[1] Есть один символ, который все еще вызывает проблемы: встроенный"
. По историческим причинам, PowerShell это не правильно проходит встроенный"
правильно для внешних программ, и досадно требует ручного\
-escaping - подробности см. в этой проблеме на GitHub. Применяется к вашему решению:& <path_to_exe> -install $user ($password -replace '"', '\"'
)
Использование приведенного ниже приведет к экранированию символов с помощью указанного вами escape-префикса. Обычный префикс перехода - \, как показано ниже. Я установил его таким образом, чтобы вам было проще добавить дополнительные символы для экранирования или изменить префикс 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
В качестве альтернативы, если вы хотите избежать стандартных метасимволов PowerShell, вы можете просто сделать
$Password = [Regex]::Escape($Password)