Inną opcją jest użycie ExpandString() np .:
$expanded = $ExecutionContext.InvokeCommand.ExpandString($template)
Invoke-Expression będzie również działać. Bądź jednak ostrożny. Obie te opcje są zdolne do wykonywania dowolnego kodu np
# 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
Jeśli chcesz mieć „bezpieczne” eval ciąg bez potencjału do przypadkowego uruchomienia kodu następnie można połączyć pracę PowerShell i ograniczony runspaces właśnie do tego np:
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
teraz jeśli spróbujesz użyć wyrażenia w ciąg, który korzysta z apletu polecenia, to nie wykona polecenia:
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
Jeśli wo Lubimy widzieć awarię, jeśli polecenie jest wykonywane, a następnie użyj $ ExecutionContext.InvokeCommand.ExpandString, aby rozwinąć parametr $ str.
Świetne pytanie! Po prostu musiałem wymyślić, jak zrobić to samo. – Noldorin
Tylko powtórzyć komentarz na odpowiedź poniżej, nie wiem sposób to zrobić (zmienne rozszerzenie), który nie pozwala na wykonywanie wyrażeń arbitralnych. Zrezygnowałem ze zmiennych powershell i wykorzystałem zmienne środowiskowe za pomocą '[System.Environment] :: ExpandEnvironmentVariables()'. Dowolne ** bezpieczne ** rozwiązanie wykorzystujące zmienne powershell byłoby bardzo interesujące! – Tao