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"

затем он выводит каждое слово на отдельном строку:

этой

и

a

строка

но если я использую одинарные кавычки, как это:

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"""

и они проходят нормально. Также, хотя scriptblocks-это скомпилированный код, он мне кажется, что они встроены в текст, если вы развернете их в строку:

> $s = { "hello" }
> "---$s---"
---"hello"---

поэтому я думаю, что вы попали в такую проблему цитирования:PowerShell удаляет двойные кавычки из аргументов командной строки и ответ Droj в частности, говоря: "странная вещь о отправке параметров во внешние программы заключается в том, что существует дополнительный уровень оценки котировок. Я не знаю, является ли это ошибкой, но я предполагаю, что это не будет изменено, потому что поведение такое же, когда вы используете Start-Process и передаете аргументы.".

PowerShell расширяет блок сценария в виде строки в вашу команду, затем эти одинарные кавычки вокруг строки переинтерпретируются как параметры кавычек и удаляются где-то в вызове. Это либо известная проблема, либо ошибка, либо по дизайну, в зависимости от того, как Вы читаете эту связанную статью connect.