Powershell: Parameterparsing/-übergabe: Token ohne Anführungszeichen, die wie benannte Argumente mit Doppelpunkt als Trennzeichen aussehen, werden bei indirekter Übergabe über $Args / @Args in zwei Teile geteilt

Erstellt am 11. März 2018  ·  3Kommentare  ·  Quelle: PowerShell/PowerShell

Verwandte: #6291, #6292 und #4624

Nachfassen von https://github.com/PowerShell/PowerShell/issues/6292#issuecomment -371344550:

Hinweis: Die fraglichen Token, wie -foo:bar , _look_ like benannte PowerShell-Argumente (und werden hinter den Kulissen zunächst immer als solche geparst - siehe Kommentar von @BrucePay unten), sollten aber als übergeben werden -is (außer um eventuell den String zu erweitern) beim Aufruf externer Programme.

Token, die zufällig wie -foo.bar aussehen, erleiden ein ähnliches Schicksal (siehe #6291).

Dies funktioniert bereits wie erwartet mit der Argumentübergabe _direct_ (z. B.
echoArgs -foo:bar übergibt -foo:bar als einzelnes Argument
), aber nicht beim Passieren von $Args / Splatting ( @Args ).

Hinweis: Das Problem ist grundlegend für die Verwendung von $Args / @Args und, obwohl es vielleicht weniger verbreitet ist, betrifft es auch seine Verwendung beim Aufrufen von PowerShell-nativen Befehlen - siehe Kommentar unten .

Schritte zum Reproduzieren

Auf macOS oder Linux ausführen.

function baz {
  bash -c 'for a; do echo $a; done' - $Args   # note: same with <strong i="32">@Args</strong>
}

baz -foo:bar
'---'
baz -foo.bar

Erwartetes Verhalten

-foo:bar
---
-foo.bar

Tatsächliches Verhalten

-foo:
bar
---
-foo
.bar

Die Argumente werden unerwartet in zwei Teile gebrochen. Siehe verlinkten Kommentar für Hintergrund.

Umgebungsdaten

PowerShell Core v6.0.1 on macOS 10.13.3
PowerShell Core v6.0.1 on Ubuntu 16.04.3 LTS
PowerShell Core v6.0.1 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Windows PowerShell v5.1.15063.674 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Issue-Discussion WG-Language

Hilfreichster Kommentar

Ich habe gerade die letzte Woche oder so damit verbracht, mit diesem Problem zu ringen. Nachdem ich die Parameterwerte des erzwungenen Wechsels (wie -foo:$bar ) verfolgt hatte, die nach dem Splating mit @Args , dachte ich, dass dies ein obskures Scoping-Problem sein muss. Stellen Sie sich meine Überraschung vor, als ich entdeckte, dass das Erzwingen eines Switch-Parameterwerts auf diese Weise nicht das erwartete Verhalten hätte. Ich habe es sogar mit der Version von Powershell 7 Preview 1 getestet und das gleiche Problem tritt immer noch auf. Ich würde hoffen, dass es nach mehr als einem Jahr als bekanntes Problem behoben wird ...

Als Referenz ist dies der Test, den ich erstellt habe, um den Fehler zu zeigen. Habe es auf einem Server 2016-Computer mit Powershell 7 Preview 1 sowie auf einem Server 2012 R2-Computer mit Powershell 5.1 gesehen.

function foo
{
    param(
        [switch]$testArg = $false
    )

    write-host "Test arg value: '$testArg'"
}

function bar
{
    foo <strong i="9">@Args</strong>
}

$testSplat = @{
    testArg = $false
}

write-host "#### Foo tests ####"

foo
foo -testArg:$true
foo -testArg:$false
foo <strong i="10">@testSplat</strong>

write-host "#### Bar tests ####"

bar
bar -testArg:$true
bar -testArg:$false
bar <strong i="11">@testSplat</strong>

Alle 3 Kommentare

Hinweis: Die fraglichen Token wie -foo:bar sehen aus wie benannte PowerShell-Argumente,

@mklement0 Wie ich in den Kommentaren in #6292 beschrieben habe, _sind_ diese PowerShell-Argumente. Stets. Die Parameterbindung erfolgt lange nach Abschluss der Kompilierung. Im kompilierten AST hat das Token für -foo: jetzt ein Flag, das anzeigt, dass im Quellcode kein Leerzeichen dahinter war. NativeCommandParameterBinder überprüft dieses AST-Element, um zu sehen, ob das Flag gesetzt ist, und verkettet dann den Parameter und das Argument ohne Leerzeichen dazwischen. Wenn es nicht gesetzt ist, wird ein Leerzeichen eingefügt. Dies funktioniert nur, wenn die Argumente literal sind (dh NativeCommandParameter war Zugriff auf den AST für das Argument). Im Splatting-Fall sind die Argumente Werte, keine wörtlichen Argumente, sodass Sie ein Leerzeichen erhalten.

Eine Möglichkeit, dies zu beheben, besteht darin, die Tokeneigenschaft "NoSpace" in Metadaten für den entsprechenden Zeichenfolgenwert zu übertragen. Das NativeCommandParameterBinder könnte dann nach diesen Metadaten suchen, wenn es sein arg-Array in einen String umwandelt. Es lohnt sich wahrscheinlich, darüber nachzudenken, ob es andere Fälle (insbesondere *nix spezifische Fälle) gibt, die angegangen werden sollten.

6492 (da als Duplikat geschlossen) zeigt, dass Splatting @args auch beim Aufrufen von PowerShell-Funktionen (nicht nur externe Programme) unterbrochen wird:

Dieses Szenario zu unterstützen ist vermutlich noch schwieriger, da hier erwartet wird, dass die benannten Parameter unverändert mit ihren ursprünglichen Typen übergeben werden.

Hier ist eine vereinfachte Reproduktion:

function b {
  Param
  (
      [Switch] $p1,
      [int] $p2,
      $rest
  )
  "`$p1: [$p1]"
  "`$p2: [$p2]"
  "`$rest: [$rest]"
}

& { b <strong i="9">@args</strong> } -p1:$false 666
$p1: [True]  # `-p1:` was interpreted as just `-p1`
$p2: [0]      # `$false`, as a separate argument, was coerced to [int] 0
$rest: [666] # what was meant to be the 2nd argument was passed as the 3rd

Die Problemumgehung – und zu Beginn die vorzuziehende Lösung – besteht darin, denselben param() Block in der Relaying-Funktion zu definieren und mit @PSBoundParameters splat.

Ich habe gerade die letzte Woche oder so damit verbracht, mit diesem Problem zu ringen. Nachdem ich die Parameterwerte des erzwungenen Wechsels (wie -foo:$bar ) verfolgt hatte, die nach dem Splating mit @Args , dachte ich, dass dies ein obskures Scoping-Problem sein muss. Stellen Sie sich meine Überraschung vor, als ich entdeckte, dass das Erzwingen eines Switch-Parameterwerts auf diese Weise nicht das erwartete Verhalten hätte. Ich habe es sogar mit der Version von Powershell 7 Preview 1 getestet und das gleiche Problem tritt immer noch auf. Ich würde hoffen, dass es nach mehr als einem Jahr als bekanntes Problem behoben wird ...

Als Referenz ist dies der Test, den ich erstellt habe, um den Fehler zu zeigen. Habe es auf einem Server 2016-Computer mit Powershell 7 Preview 1 sowie auf einem Server 2012 R2-Computer mit Powershell 5.1 gesehen.

function foo
{
    param(
        [switch]$testArg = $false
    )

    write-host "Test arg value: '$testArg'"
}

function bar
{
    foo <strong i="9">@Args</strong>
}

$testSplat = @{
    testArg = $false
}

write-host "#### Foo tests ####"

foo
foo -testArg:$true
foo -testArg:$false
foo <strong i="10">@testSplat</strong>

write-host "#### Bar tests ####"

bar
bar -testArg:$true
bar -testArg:$false
bar <strong i="11">@testSplat</strong>
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen