2009-07-04 9 views
7

Czy ktoś może wyjaśnić, dlaczego ten skrypt zgłasza wyjątek?Powershell Script kończy się niepowodzeniem po uzyskaniu dostępu do właściwości Array.Length

$byteArray = @(1,2,3) 
write-Output ("{0:X}{1:X}{2:X}" -f $byteArray) 
write-Output ($byteArray.Length -ge 3) 
write-Output ("{0:X}{1:X}{2:X}" -f $byteArray) 

Zasadniczo tworzę tablicę liczb, formatowanie tablicę, a następnie sprawdzając jego długość i formatowanie go ponownie.

Pierwszy format powiodło się, ale drugi format zgłasza wyjątek.

123 
True 
-------------------------------------------------------------------------------- 
POWERSHELL EXCEPTION 
EXCEPTION TYPE:System.Management.Automation.RuntimeException 
MESSAGE:Error formatting a string: Index (zero based) must be greater than or equal to zero and less than the size of the argument list.. 
POSITION: 
At line:4 char:36 
+ write-Output ("{0:X}{1:X}{2:X}" -f <<<< $byteArray) 
-------------------------------------------------------------------------------- 
+0

Czy powinno to być na ServerFault? Może nie dlatego, że jest to skrypt, ale nie skrypt administratora? –

+4

Nie powinno, ponieważ jest to wyraźnie pytanie o dziwne zachowanie programu, a nie abuot administrowania niczego. – Joey

+0

+1. To jest fascynujące pytanie (do mnie), a nie w ogóle związane z administratorem. –

Odpowiedz

3

To zdecydowanie dziwne. Jako obejście można użyć

"{0:X}{1:X}{2:X}" -f @($byteArray) 

który wydaje się działać, nawet po wejściu członków $byteArray.

Innym możliwym obejściem problemu może być zapisanie sformatowanego ciągu w zmiennej i ponowne użycie.

Jeśli chodzi o dlaczego nie działa po uzyskaniu dostępu do nieruchomości Length, nie mam pojęcia.

+1

Dzięki. To ta sama praca, którą używam. Wydaje się, że jeśli skopiujesz tablicę do nowej zmiennej, możesz użyć tej zmiennej dla wszystkich wywołań formatujących i żaden wyjątek nie zostanie zgłoszony. – kervin

+0

W pewien sposób dostęp do elementu zmienia coś w tablicy, które wyzwala to zachowanie przy pomocy -f. Może jeden z twórców Powershell wie, co się dzieje. – Joey

1

Wow, to dość fascynujące. Grałem z tym przez kilka minut w PowerShell V2 i nie mogę znaleźć twardego i szybkiego powodu, dlaczego tak się dzieje.

Ale to nie powstrzyma mnie od spekulacje :)

Problemem jest to, że polecenie -f jest naprawdę spodziewa tablicę obiektów. To, co wyraźnie dzieje się w linii problemu, polega na tym, że interpretuje on $ byteArray jako pojedynczy element względem tablicy.

Ale dlaczego działa po raz pierwszy? Moim podejrzeniem jest to, że tablica jest leniwo oceniana. Dopóki nie wywołasz metody na typ tablicy, jest to tylko alias do potoku. Przez jakąś rzecz działa w pierwszym przypadku, ponieważ jest to indeksowanie do istniejącej linii rurowej lub argumentów. Po wywołaniu .Length, tworzy potok potoku w obiekcie, a następnie wywołuje poprawnie interpretuje go jako tablicę.

To znowu tylko spekulacja. Bardzo radzę złożyć błąd w łączach, ponieważ to pachnie jak błąd.

4

Aby dodać do układanki:

PS > $a = @(1,2,3) 
PS > $b = $a 
PS > [object]::ReferenceEquals($a, $b) 
True 
PS > $a.Length 
3 
PS > [object]::ReferenceEquals($a, $b) 
True 
PS > "{0:X}{1:X}{2:X}" -f $a 
Error formatting a string: Index (zero based) must be greater than or equal to zero and less than the size of the argum 
ent list.. 
At line:1 char:21 
+ "{0:X}{1:X}{2:X}" -f <<<< $a 
PS > "{0:X}{1:X}{2:X}" -f $b 
123 
PS > $b.GetLength(0) 
3 
PS > "{0:X}{1:X}{2:X}" -f $b 
123 
PS > [object]::ReferenceEquals($a, $b) 
True 

I raczej się zgadza z Jaredem, że to dziwactwo operatora -f widząc zmienną jako obiekt zamiast tablicy, wspierany częściowo przez to:

PS > $a = @(1,2,3) 
PS > "{0:X}{1:X}{2:X}" -f $a 
123 
PS > "{0:X}{1:X}{2:X}" -f $a.PSObject 
Error formatting a string: Index (zero based) must be greater than or equal to zero and less than the size of the argum 
ent list.. 
At line:1 char:21 

Jeżeli bazowy obiekt nie jest do zaakceptowania jako parametr, to musi być coś specjalnego, jak $a jest oryginalnie przechowywane sprawia, że ​​-f zadowolony. Ale to nadal nie wyjaśnia, dlaczego wywołanie GetLength() nie wpływa na "arrayness" $b w sposób, w jaki wydaje się, że Length (i Rank).

Jak zauważyli inni, używanie @() wydaje się działać konsekwentnie.

Powiązane problemy