Как я могу предотвратить (сериализованное) выражение, чтобы развернуть - PullRequest
5 голосов
/ 29 июня 2019

Благодаря режиму выражения PowerShell, PowerShell имеет несколько хороших способов десериализации объектов, таких как:

Мое общее ожидание состоит в том, что результат данного выражения должен совпадать с использованием одной из перечисленных выше команд десериализации для той же сериализованной версии этого выражения (для справки см. ConvertTo-Expression ответ на 'Сохранить хэш-таблицу в нотации объектов PowerShell (PSON)' вопрос).
Другими словами:

<Expression> <=> Invoke-Command {<Expression>} <=> &([ScriptBlock]::Create('<Expression>'))
<Expression> <=> Invoke-Expression '<Expression>'

Примеры:

Get-ChildItem <=> &{Get-ChildItem}
Get-ChildItem <=> Invoke-Command {Get-ChildItem}
Get-ChildItem <=> Invoke-Expression 'Get-ChildItem'

1, 2, 3 <=> &{1, 2, 3}
1, 2, 3 <=> Invoke-Command {1, 2, 3}
1, 2, 3 <=> Invoke-Expression '1, 2, 3'

Это действительно кажется верным в основном для каждого выражения, но из-за того, что PowerShell разворачивает (перечисляет) выходные данные по умолчанию, это определение отклоняется в случае, если выражение содержит массив с одним элементом:

,1 <≠> Invoke-Command {,1}
,1 <≠> Invoke-Expression ',1'
,"Test" <≠> Invoke-Command {,"Test"}
,"Test" <≠> Invoke-Expression ',"Test"'
@("Test") <≠> Invoke-Command {@("Test")}
@("Test") <≠> Invoke-Expression '@("Test")'
,@("Test") <≠> Invoke-Command {,@("Test")}
,@("Test") <≠> Invoke-Expression ',@("Test")'

Есть ли способ предотвратить развертывание выражений при их вызове (десериализации)?

Я рассматриваю запрос на параметр -NoEnumerate (аналогично командлету Write-Output) для Invoke-Expression на PowerShell GitHub , но это все равно оставит вопрос / вопрос для оператора вызова и точечного поиска, которые не поддерживают параметры ...

1 Ответ

0 голосов
/ 12 июля 2019

Я нашел обходной путь для предотвращения развертывания (сериализованных) выражений по умолчанию:
Обернуть выражение в HashTable :

<Expression> <=> (Invoke-Command {@{e=<Expression>}})['e']
<Expression> <=> (Invoke-Expression '@{e=<Expression>}')['e']

Примеры:

Get-ChildItem <=> (Invoke-Command {@{e=Get-ChildItem}})['e']
Get-ChildItem <=> (Invoke-Expression '@{e=Get-ChildItem}')['e']

1, 2, 3 <=> (Invoke-Command {@{e=1, 2, 3}})['e']
1, 2, 3 <=> (Invoke-Expression '@{e=1, 2, 3}')['e']

,1 <=> (Invoke-Command {@{e=,1}})['e']
,1 <=> (Invoke-Expression '@{e=,1}')['e']

Я реализовал это в командлете ConvertFrom-Expression , который следующие функции:

  • -NoEnumerate переключатель для предотвращения развертывания массивов с одним элементом
  • -NoNewScope переключатель, аналогичный Invoke-Command
  • Несколько ScriptBlock и / или Строковые элементы через конвейер или аргумент -Expression

ConvertFrom-Expression Примеры:

PS C:>'2*3', {3*4}, '"Test"' | ConvertFrom-Expression
6
12
Test

PS C:> (ConvertFrom-Expression ',"Test"' -NoEnumerate) -Is [Array]
True
...