PowerShell, выполняющий функцию в блоке скрипта с помощью Start-Process, делает странные вещи с двойными кавычками
У меня есть скрипт PowerShell, который редактирует реестр, поэтому он должен работать от имени администратора. Для этого я запускаю новый процесс PowerShell из запущенного сценария PowerShell и передаю часть пути раздела реестра, используя блок сценария с функцией в нем. Когда я использую двойные кавычки в этой функции, PowerShell пытается интерпретировать их как команды, а не строку. Если я использую одинарные кавычки, то все работает нормально.
Я создал немного урезанный образец сценарий powershell, который воспроизводит проблему. Вот фрагмент:
$ScriptBlock = {
function Test
{
$status = "This is a string"
Write-Output $status
}
}
Start-Process -FilePath PowerShell -ArgumentList "-NoExit -NoProfile -ExecutionPolicy Bypass -Command & {$ScriptBlock Test}"
Таким образом, в новом процессе PowerShell сначала определяется код в блоке скрипта, а затем вызывается тестовый метод, и он выдает следующую ошибку:
This: термин "This" не распознается как имя командлета, функция, файл сценария или действующая программа. Проверьте правильность написания имя, или если путь был включен, убедитесь, что путь правильный и попробовать еще раз.
Итак он пытается рассматривать строку как запятую, как если бы я только что набрал This is a string
сам по себе на новой строке в моем сценарии.
Если я изменю строку
$status = "This is a string"
To
$status = 'This is a string'
Скрипт работает как ожидалось и просто выводит строку This is a string
.
Еще одна странная проблема, которую я заметил, заключается в том, что если я не использую переменную, а просто использую:
Write-Output "This is a string"
Затем он выводит каждое слово на отдельной строке следующим образом:
Это
Is
A
Строка
Но если я использую одинарные кавычки, как это:
Write-Output 'This is a string'
Затем он выводит все предложение на одной строке, как и ожидалось.
Кто-нибудь знает, почему PowerShell ведет себя странно в таких ситуациях?Ответ
Так что, как упоминает Тесселлатингхеклер, решение заключается в том, чтобы обернуть все, что находится в двойных кавычках, в двойные двойные кавычки, одинарные кавычки или вы можете использовать скобки.
Таким образом, в моем примере вы бы изменение:
$status = "This is a string"
К этому:
$status = """This is a string"""
Или вот это:
$status = '"This is a string"'
Или вот это:
$status = {"This is a string"}
Если вы хотите оценить переменную в вашей строке (т. е. увидеть значение переменной), то вам нужно использовать метод двойных кавычек:
$status = """This is a string that evaluates $someVariable"""
Все еще не уверен, является ли это ошибкой или по замыслу, но, по крайней мере, у нас есть обходной путь, так как это устраняет обе проблемы, которые я описал выше.
1 ответ:
Если я изменю ваш сценарий на
-Command $ScriptBlock
Запустите его, и пусть он откроет новое окно оболочки, а затем запустите
gci function:test | fl
Чтобы увидеть определение функции в новом окне, показан код
$status = This is a string
С тем же тестом на версии с одной кавычкой он показывает
$status = 'This is a string'
Таким образом, он теряет двойные кавычки. Избавьтесь от них с помощью двойных кавычек
$status = """This is a string"""
И они проходят нормально. Кроме того, хотя scriptblocks-это скомпилированный код, мне кажется, что они встроены в текст, если вы разворачиваете их в строку:
> $s = { "hello" } > "---$s---" ---"hello"---
Поэтому я думаю, что вы сталкиваетесь с такой проблемой цитирования: PowerShell удаляет двойные кавычки из аргументов командной строки и ответDroj в частности, говоря: "странная вещь в отправке параметров внешним программам заключается в том, что существует дополнительный уровень оценки цитат. Я не знаю, является ли это ошибкой, но я предполагаю, что это не будет изменено, потому что поведение такое же, когда вы используете Start-Process и проходите в аргументы.".
PowerShell разворачивает блок скрипта в виде строки в вашу команду, затем эти одиночные кавычки вокруг строки интерпретируются как параметры в кавычках и удаляются где-то в вызове. Что является либо известной проблемой, либо ошибкой, либо по замыслу, в зависимости от того, как Вы читаете эту связанную статью connect.