Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell Script fails after accessing Array.Length Property

Tags:

powershell

Can someone explain why this script throws an exception?

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

Basically, I am creating an array of numbers, formatting the array and then checking its length and formatting it again.

The first format succeeds, but the second format throws an exception.

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 )
--------------------------------------------------------------------------------
like image 826
kervin Avatar asked Jul 04 '09 00:07

kervin


People also ask

How do I get the length of an array in PowerShell?

Count or Length or LongLength To determine how many items are in an array, use the Length property or its Count alias. Longlength is useful if the array contains more than 2,147,483,647 elements.

How do you access array elements in PowerShell?

The array elements are accessed through the index. Array indices are 0-based; that is, they start from 0 to arrayRefVar. length-1.

What does @() mean in PowerShell?

Array subexpression operator @( )Returns the result of one or more statements as an array. The result is always an array of 0 or more objects. PowerShell Copy.

What is @{} in PowerShell?

@{} in PowerShell defines a hashtable, a data structure for mapping unique keys to values (in other languages this data structure is called "dictionary" or "associative array"). @{} on its own defines an empty hashtable, that can then be filled with values, e.g. like this: $h = @{} $h['a'] = 'foo' $h['b'] = 'bar'


2 Answers

To add to the puzzle:

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 tend to agree with Jared that it's a quirk of the -f operator seeing the variable as an object rather than an array, supported in part by this:

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

If the underlying object isn't acceptable as a parameter, then there must be something special about how $a is originally stored that makes -f happy. But that still doesn't explain why calling GetLength() doesn't affect $b's "arrayness" in the way that Length (and Rank) seem to.

As others have noted, using @() does seem to work consistently.

like image 102
dahlbyk Avatar answered Oct 10 '22 10:10

dahlbyk


That's definitely weird. As a workaround you can use

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

which seems to work even after accessing members of $byteArray.

Another possible workaround might be to save the formatted string to a variable and re-use it.

As for why it doesn't work after accessing the Length property I have no idea.

like image 21
Joey Avatar answered Oct 10 '22 11:10

Joey