2012-07-23 5 views
8

Das folgende Powershell-Skript veranschaulicht das Problem:

$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 

Wer weiß, warum die $hash.key Syntax überall, aber innerhalb expliziter Erweiterung funktioniert? Kann dies behoben werden, oder muss ich es saugen und mit der $hash[''key''] Syntax leben?

+1

Es ist eigentlich noch schlimmer als das - ich kann nicht get * any * tatsächlicher Teilausdruck mit dieser Syntax erweitert, funktionieren nur einfache Dinge wie $ ($ foo) '$ (Get-Date | select -expand DayOfWeek)' löst dieselbe Ausnahme aus. Schlagen Sie vor, es auf connect zu melden, IMO, das Änderung/Programmfehler bricht. – BartekB

+0

Melde es wo? Ich weiß nicht, was "verbinden" in diesem Zusammenhang bedeutet. –

+1

Entschuldigung, sollte spezifischer sein ...: http://connect.microsoft.com/powershell -> der beste Ort, um solche Probleme zu melden. – BartekB

Antwort

1

Die ExpandString API ist nicht genau für die Verwendung von PowerShell-Skripten gedacht, sondern wurde für C# -Code hinzugefügt. Es ist immer noch ein Fehler, dass Ihr Beispiel nicht funktioniert (und ich denke, dass es in V4 behoben wurde), aber es bedeutet, dass es einen Workaround gibt - einen, den ich für den allgemeinen Gebrauch empfehle.

Double zitierte Strings effektiv (aber nicht wörtlich) rufen ExpandString. So sollte die folgende entsprechen:

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

Wie verzögern Sie die Verarbeitung einer Zeichenfolge mit doppelten Anführungszeichen? Der Grund dafür ist, dass Variablen, die nicht existieren, wenn der String $ ($ hash.a) definiert ist, zur Laufzeit in das Ergebnis eingebettet werden können. –

+0

Die Verarbeitung einer doppelten Zeichenfolge in Anführungszeichen geschieht, wenn der Ausdruck ausgeführt wird, nicht bei der Analyse. Mit anderen Worten, die Verarbeitung geschieht wie bei einem Aufruf der ExpandString api. –

+0

Welches beantwortet die Frage nicht. Wie würden Sie $ str codieren, so dass dieses Beispiel 'After' schreibt? '$ hash ['a'] = 'Vorher': $ str = '$ ($ hash.a)': $ hash ['a'] = 'Nachher': Write.Host $ ExecutionContext.InvokeCommand.ExpandString ($ str) ' –

1

Ich habe versucht, Text zu speichern, die den Benutzer in einer Textdatei auffordert. Ich wollte Variablen in der Textdatei haben können, die von meinem Skript erweitert werden.

Meine Einstellungen sind in einem PSCustomObject namens $ Profil und so in meinem Text gespeichert Ich habe versucht, so etwas wie zu tun:

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

und dann von meinem Skript Ich habe versucht zu tun:

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

die natürlich mich mit dem Fehler links

Ausnahme calling "ExpandString" mit "1" Argument (e): „Objekt Referenz nicht auf eine Instanz eines Objekts gesetzt. "

Schließlich habe ich herausgefunden Ich musste nur die PSCustomObject Werte speichern ich in regelmäßigen alten Variablen wollen, um die Textdatei ändern schön diejenigen anstelle der object.property Version und alles funktionierte zu verwenden:

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

Und im Text habe ich geändert in

Hallo $ First $ Last !!!

4

Ich benutze diese Methode, da dieser Fehler in v4 vorhanden ist (nicht in v5)

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

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

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

Verwendung für Ihr Beispiel:

'$($hash.a)' | render 
Verwandte Themen