2012-07-23 130 views
8

下面的PowerShell脚本演示了这个问题:

$hash = @{'a' = 1; 'b' = 2} 
Write-Host $hash['a']  # => 1 
Write-Host $hash.a   # => 1 

# Two ways of printing using quoted strings. 
Write-Host "$($hash['a'])" # => 1 
Write-Host "$($hash.a)"  # => 1 

# And the same two ways Expanding a single-quoted string. 
$ExecutionContext.InvokeCommand.ExpandString('$($hash[''a''])') # => 1 
$ExecutionContext.InvokeCommand.ExpandString('$($hash.a)')  # => Oh no! 

Exception calling "ExpandString" with "1" argument(s): "Object reference not set to an instance of an object." 
At line:1 char:1 
+ $ExecutionContext.InvokeCommand.ExpandString('$($hash.a)') 
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [], MethodInvocationException 
    + FullyQualifiedErrorId : NullReferenceException 

任何人都知道为什么$hash.key语法作品无处不在,但明确的扩张里面?这可以修复吗?还是我必须吸取它并与$hash[''key'']语法一起生活?

+1

它实际上比这更糟糕 - 我不能得到*任何*实际的子表达式扩展使用这种语法,只有简单的东西,如$($ foo)工作,例如'$(Get-Date | select -expand DayOfWeek)'会引发同样的异常。建议在连接上报告它,这是突破变化/错误的IMO。 – BartekB 2012-07-23 11:38:00

+0

报告它在哪里?在这种情况下,我不知道“连接”是什么意思。 – 2012-07-23 15:49:01

+1

对不起,应该更具体......:http://connect.microsoft.com/powershell->报告这类问题的最佳地点。 – BartekB 2012-07-23 21:58:19

回答

1

ExpandString api并非完全适用于PowerShell脚本,它更多地用于C#代码。这仍然是一个错误,您的示例不起作用(我认为它已在V4中得到修复),但这确实意味着有一种解决方法 - 我推荐一种常用的解决方法。

双引号字符串有效(但不是字面上)调用ExpandString。所以下面应该是等效的:

$ExecutionContext.InvokeCommand.ExpandString('$($hash.a)') 
"$($hash.a)" 
+0

那么你如何延迟处理双引号字符串?这样做的全部原因是,当定义字符串“$($ hash.a)”时不存在的变量可以在运行时嵌入到结果中。 – 2013-09-26 02:45:35

+0

双引号字符串的处理在执行表达式时发生,而不是在被解析时发生。换句话说,如果您调用ExpandString api,处理就会发生。 – 2013-09-26 03:49:56

+0

哪个不回答问题。你将如何编码$ str,以便这个例子写'后'? $ hash ['a'] ='Before':$ str ='$($ hash.a)':$ hash ['a'] ='After':Write.Host $ ExecutionContext.InvokeCommand.ExpandString($ str )' – 2013-09-27 21:58:56

1

我试图存储在文本文件中提示用户的文本。我希望能够在我的脚本中扩展的文本文件中具有变量。

我的设置存储在一个PSCustomObject名为$异型材等在我的文字我试图做这样的事情:

Hello $($profile.First) $($profile.Last)!!! 

,然后从我的剧本,我试图做的事:

$profile=GetProfile #Function returns PSCustomObject 
$temp=Get-Content -Path "myFile.txt" 
$myText=Join-String $temp 
$myText=$ExecutionContext.InvokeCommand.ExpandString($myText) 

这当然给我留下误差

异常呼叫“ExpandString”与“1”的参数(一个或多个):“对象 引用未设置为对象的实例。“

最后我想通了,我只需要存储PSCustomObject值我要以普通旧变量,更改文本文件中使用的,而不是object.property版本,一切都很好地工作:

$profile=GetProfile #Function returns PSCustomObject 
$First=$profile.First 
$Last=$profile.Last 
$temp=Get-Content -Path "myFile.txt" 
$myText=Join-String $temp 
$myText=$ExecutionContext.InvokeCommand.ExpandString($myText) 

而在正文中我更改为

Hello $ First $ Last !!!

4

我用这个方法,因为这个bug在V4(未在V5)

function render() { 
    [CmdletBinding()] 
    param ([parameter(ValueFromPipeline = $true)] [string] $str) 

    #buggy 
    #$ExecutionContext.InvokeCommand.ExpandString($str) 

    "@`"`n$str`n`"@" | iex 
} 

使用您的例子存在:

'$($hash.a)' | render 
相关问题