简体   繁体   中英

Safe late variable expansion in Powershell

I found a very old thread here that seemed to answer the question, but when I tried to implement the code I am not getting the expected variable expansion. Based on this

$Arguments = '$foo (Notepad.exe) bar'
$foo = 'Foooooo'
$InitSB = {$ExecutionContext.SessionState.Applications.Clear(); $ExecutionContext.SessionState.Scripts.Clear(); Get-Command | %{$_.Visibility = 'Private'}}
$SafeStringEvalSB = {param($str) $str}
$job = Start-Job -Init $InitSB -ScriptBlock $SafeStringEvalSB -ArgumentList $Arguments
Wait-Job $job > $null
Receive-Job $job

I would expect to get back Foooooo (Notepad.exe) bar

What have I got wrong here? And is there any difference between v2 and later versions? I do have this working using $ExecutionContext.InvokeCommand.ExpandString(), but that allows for arbitrary code to execute as well, which I am trying to avoid. Ultimately I have a large number of different strings stored in XML, with different permutations of variables interspersed in the strings, and the actual values of those different variables are assigned at run time. And I need to push those values into the specific string of many possible wherever they occur. Because there are so many potential strings and variables I can't easily use a simple format approach. So ultimately I need the functionality of $ExecutionContext.InvokeCommand.ExpandString() but limited to actually just expanding variables, with no other code execution. Any help greatly appreciated.

Alternatively you could just replace the text.

Param($var1,$var2,$var3)
$Content = Get-Content C:\Path\To\file.xml
$Content -replace '\$var1', "$var1" -replace '\$var2', "$var2" -replace '\$var3', "$var3"

As you have it written you won't get what you expect purely because you have single quotes around your string that you are assigning to $Arguments, meaning $foo wouldn't be treated as a variable anyway.

EDIT: Still won't work even with double quotes. Must assign value to $foo before referencing it in $Arguments.

$foo = 'Foooooo'
$Arguments = "$foo (Notepad.exe) bar"
$InitSB = {$ExecutionContext.SessionState.Applications.Clear(); $ExecutionContext.SessionState.Scripts.Clear(); Get-Command | %{$_.Visibility = 'Private'}}
$SafeStringEvalSB = {param($str) $str}
$job = Start-Job -Init $InitSB -ScriptBlock $SafeStringEvalSB -ArgumentList $Arguments
Wait-Job $job > $null
Receive-Job $job

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM