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 расширяет блок сценария как строку в вашей команде, затем эти одинарные кавычки вокруг строки переопределяются как параметры в кавычках и удаляются где-то в вызове. Что является либо известной проблемой, либо ошибкой, либо побочным дизайном, в зависимости от того, как вы прочитали эту связанную статью о соединении.

Другие вопросы по тегам