2014-05-13 47 views
6

To pytanie jest podobne do Passing empty arguments to executables using powershell, ale chcę rozszerzyć zarówno pytanie, jak i odpowiedź i lepiej zrozumieć "dlaczego", ponieważ wydaje się pułapką PowerShell.Dlaczego PowerShell inaczej traktuje pusty ciąg znaków w wierszu poleceń?

Jeśli załadować PSCX i uruchomić echoargs (polecenie zewnętrzne, czyli pliku exe) widać, że pusty ciąg argumentem jest pomijany:

PS> echoargs word "two words" "" 123 
Arg 0 is <word> 
Arg 1 is <two words> 
Arg 2 is <123> 

Ale jeśli używasz „CMD ucieczki” (--%) można się wydawać „prawidłowo”:

PS> echoargs --% word "two words" "" 123 
Arg 0 is <word> 
Arg 1 is <two words> 
Arg 2 is <> 
Arg 3 is <123> 

Podobnie jeśli ktoś pisze PowerShell funkcjonować pusty łańcuch jest prawidłowo obsługiwane:

PS> Show-Args word "two words" "" 123 
Arg 0 is <word> 
Arg 1 is <two words> 
Arg 2 is <> 
Arg 3 is <123> 

Ta różnica wydaje mi się bardzo ważna z następującego powodu. Przykłady pokazane powyżej używają literalnego pustego ciągu w linii poleceń, więc przynajmniej masz podpowiedź problemu. Ale wyniki są dokładnie takie same, jeśli używa się zmiennej zawierającej pusty ciąg. Oznacza to, trzeba albo:

  1. ściśle nadzorować wszystkie zmienne są doprowadzane do zewnętrznych poleceń lub
  2. użyciu wydostawaniu CMD (-%) i zrezygnować z wykorzystaniem dowolnej PowerShell konstruktów resztą linii
  3. zacytować każdy argument do zewnętrznego polecenia z backquote/podwójny cudzysłów jak `"this`" lub `"$this`" lub `"`"

... lub złe rzeczy będzie się działo!

(@KeithHill wskazał trzecią obejście wyżej więc dodałem go tam dla kompletności. To działa dla literałów lub zmiennych tak, choć brzydki, to chyba najlepszy wybór z trzech obejścia.)

Tak PowerShell obsługuje argumenty funkcji odmiennie niż argumenty zewnętrznego polecenia - w sposób dramatyczny. Czy to jest niespójność w zachowaniu PowerShell? Jeśli nie, dlaczego nie?


Uzupełnienie

Dla porównania, oto ciało funkcja PowerShell używany powyżej:

function Show-Args() 
{ 
    for ($i = 0; $i -lt $args.length; $i++) 
    { 
     Write-Host ("Arg {0} is <{1}>" -f $i, $args[$i]) 
    } 
} 

I Oto echoargs równoważne w C#:

class Program 
{ 
    static void Main(string[] args) 
    { 
     for (int i = 0; i < args.Length; i++) 
     { 
      System.Console.WriteLine("Arg {0} is <{1}>", i, args[i]); 
     } 
    } 
} 

Odpowiedz

2

zachowanie może być uznane za "z założenia" (trudno jest kn ow na pewno w oparciu o wdrożenie i testy), ale nie sądzę, aby kwestia była zbytnio przemyślana, a ty przynosisz świetne punkty.

Osobiście uważam, że masz rację, a PowerShell jest niespójny. Warto zauważyć, że zmiana jest spójna, choć wiąże się to z ryzykiem zerwania istniejących skryptów.

+1

Tak, obsługa pustych argumentów napisów w aplikacjach wydaje się nieprawidłowa. ;-) Aby być uczciwym, ten problem istnieje co najmniej aż do V2. –

Powiązane problemy