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:
- ściśle nadzorować wszystkie zmienne są doprowadzane do zewnętrznych poleceń lub
- użyciu wydostawaniu CMD (-%) i zrezygnować z wykorzystaniem dowolnej PowerShell konstruktów resztą linii
- 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]);
}
}
}
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. –