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 он сначала определит код в блоке сценария, а затем вызовет метод Test и выдаст следующую ошибку:
This: Термин "This" не распознается как имя командлета, функции, файла сценария или работоспособной программы. Проверьте правильность написания имени или, если путь был указан, проверьте правильность пути и повторите попытку.
Поэтому он пытается обработать строку как запятую, как будто я только что набрал This is a string
само по себе на новой строке в моем сценарии.
Если я изменю линию
$status = "This is a string"
в
$status = 'This is a string'
скрипт работает как положено и просто выводит строку This is a string
,
Другая странная проблема, которую я заметил, заключается в том, что если я не использую переменную и просто использую:
Write-Output "This is a string"
затем выводит каждое слово в отдельной строке, например:
это
является
строка
но если я использую одинарные кавычки, как это:
Write-Output 'This is a string'
затем выводит все предложение в одну строку, как и ожидалось.
Кто-нибудь знает, почему PowerShell ведет себя странно в таких ситуациях?
Ответ
Так, как упоминает TessellatingHeckler, решение заключается в том, чтобы заключить все, что в двойные кавычки, одинарные кавычки, или вы можете использовать скобки.
Так что в моем примере вы бы изменили:
$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"""
и они приходят через ОК. Также, хотя блоки скриптов являются скомпилированным кодом, мне кажется, что они встроены в текст, если вы развернете их в строку:
> $s = { "hello" }
> "---$s---"
---"hello"---
Поэтому я думаю, что вы сталкиваетесь с такой проблемой цитирования: PowerShell отбирает двойные кавычки из аргументов командной строки и, в частности, отвечает Дрой, говоря: "Странная вещь при отправке параметров во внешние программы заключается в том, что существует дополнительный уровень оценки цитат. I Не знаю, является ли это ошибкой, но я предполагаю, что она не изменится, потому что поведение при запуске Start-Process и передаче аргументов одинаково."
PowerShell расширяет блок сценария как строку в вашей команде, затем эти одинарные кавычки вокруг строки переопределяются как параметры в кавычках и удаляются где-то в вызове. Что является либо известной проблемой, либо ошибкой, либо побочным дизайном, в зависимости от того, как вы прочитали эту связанную статью о соединении.