2012-07-23 6 views
8

La siguiente secuencia de comandos de PowerShell demuestra el problema:

$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 

Alguien sabe por qué la sintaxis $hash.key funciona en todas partes, pero dentro de expansión explícito? ¿Se puede arreglar esto, o tengo que hacerlo funcionar y vivir con la sintaxis $hash[''key'']?

+1

En realidad es peor que eso - no puedo obtener * cualquier * subexpresión real expandida usando esta sintaxis, solo cosas simples como $ ($ foo) funcionan, por ejemplo '$ (Get-Date | select -expand DayOfWeek)' levantará la misma excepción. Sugerir informar sobre Connect, IMO que está rompiendo cambio/error. – BartekB

+0

¿Cómo informar sobre dónde? No sé lo que significa 'conectar' en este contexto. –

+1

Lo sentimos, debería ser más específico ...: http://connect.microsoft.com/powershell -> el mejor lugar para informar tales problemas. – BartekB

Respuesta

1

La API de ExpandString no está pensada para el uso de las secuencias de comandos de PowerShell, sino que se agregó más para el código de C#. Todavía es un error que su ejemplo no funcione (y creo que se ha solucionado en V4), pero significa que hay una solución alternativa, una que recomiendo para uso general.

Las cadenas entre comillas dobles efectivamente (pero no literalmente) llaman a ExpandString. Por lo tanto, lo siguiente debería ser equivalente:

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

Entonces, ¿cómo se puede retrasar el procesamiento de una cadena de comillas dobles? La razón completa para hacer esto es para que las variables que no existen cuando se define la cadena ''$ ($ hash.a)'' se puedan incrustar en el resultado en el tiempo de ejecución. –

+0

El procesamiento de una cadena con comillas dobles ocurre cuando la expresión se ejecuta, no cuando se analiza. En otras palabras, el procesamiento ocurre como lo haría si llamaras a la apéndice ExpandString. –

+0

que no responde la pregunta. ¿Cómo codificaría $ str para que este ejemplo escriba 'Después'? '$ hash ['a'] = 'Antes': $ str = '$ ($ hash.a)': $ hash ['a'] = 'Después': Write.Host $ ExecutionContext.InvokeCommand.ExpandString ($ str) ' –

1

Estaba tratando de almacenar el texto que solicita al usuario en un archivo de texto. Quería poder tener variables en el archivo de texto que se expanden desde mi script.

Mis ajustes se almacenan en un PSCustomObject llamado perfil $ y así en mi texto yo estaba tratando de hacer algo como:

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

y después de mi guión que estaba tratando de hacer:

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

que por supuesto me dejó con el error

Excepción llamada "ExpandString" con el argumento "1" (s): "objeto referencia no establecida en una instancia de un objeto. "

Finalmente me di cuenta de que sólo necesitaba para almacenar los valores PSCustomObject que quiero en las variables de edad regulares, cambiar el archivo de texto a utilizar aquellos en vez de la versión object.property y todo funcionaba muy bien:

$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) 

Y en el texto que cambié a

Hola $ First $ Last !!!

4

Puedo usar este método, ya que existe este error en v4 (no en v5)

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

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

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

uso por su ejemplo:

'$($hash.a)' | render 
Cuestiones relacionadas