Ответ 1
Другой вариант - использовать ExpandString(), например:
$expanded = $ExecutionContext.InvokeCommand.ExpandString($template)
Вызов-выражение также будет работать. Однако будьте осторожны. Обе эти опции способны выполнять произвольный код, например:
# Contents of file template.txt
"EvilString";$(remove-item -whatif c:\ -r -force -confirm:$false -ea 0)
$template = gc template.txt
iex $template # could result in a bad day
Если вы хотите иметь "безопасную" строку eval без возможности случайного запуска кода, вы можете комбинировать задания PowerShell и ограниченные пробелы, чтобы сделать это, например:
PS> $InitSB = {$ExecutionContext.SessionState.Applications.Clear(); $ExecutionContext.SessionState.Scripts.Clear(); Get-Command | %{$_.Visibility = 'Private'}}
PS> $SafeStringEvalSB = {param($str) $str}
PS> $job = Start-Job -Init $InitSB -ScriptBlock $SafeStringEvalSB -ArgumentList '$foo (Notepad.exe) bar'
PS> Wait-Job $job > $null
PS> Receive-Job $job
$foo (Notepad.exe) bar
Теперь, если вы попытаетесь использовать выражение в строке, использующей командлет, это не приведет к выполнению команды:
PS> $job = Start-Job -Init $InitSB -ScriptBlock $SafeStringEvalSB -ArgumentList '$foo $(Start-Process Notepad.exe) bar'
PS> Wait-Job $job > $null
PS> Receive-Job $job
$foo $(Start-Process Notepad.exe) bar
Если вы хотите увидеть сбой при попытке выполнить команду, используйте $ExecutionContext.InvokeCommand.ExpandString, чтобы развернуть параметр $str.