Powershell V2 – CannotIndex error when working with arrays
Warning! Out of date content.
Ever had the cannotindex runtime exception when working with powershell arrays?
I present the following situation:
Create three .txt files and verify their creation with get-childitem *.txt.
PS C:\Users\administrator.HOMELAB> echo 1 > 1.txt
PS C:\Users\administrator.HOMELAB> echo 2 > 2.txt
PS C:\Users\administrator.HOMELAB> echo 3 > 3.txt
PS C:\Users\administrator.HOMELAB> Get-ChildItem *.txt
Directory: C:\Users\administrator.HOMELAB
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 10/27/2013 7:12 PM 8 1.txt
-a--- 10/27/2013 7:12 PM 8 2.txt
-a--- 10/27/2013 7:12 PM 8 3.txt
Now place the result of get-childitem in a variable called txt and query the different elements in the array.
PS C:\Users\administrator.HOMELAB> $txt = Get-ChildItem *.txt
PS C:\Users\administrator.HOMELAB> $txt[0]
Directory: C:\Users\administrator.HOMELAB
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 10/27/2013 7:12 PM 8 1.txt
PS C:\Users\administrator.HOMELAB> $txt[1]
Directory: C:\Users\administrator.HOMELAB
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 10/27/2013 7:12 PM 8 2.txt
PS C:\Users\administrator.HOMELAB> $txt[2]
Directory: C:\Users\administrator.HOMELAB
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 10/27/2013 7:12 PM 8 3.txt
PS C:\Users\administrator.HOMELAB> $txt[-1]
Directory: C:\Users\administrator.HOMELAB
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 10/27/2013 7:12 PM 8 3.txt
Everything seems to work fine. Now remove the first two files, only leaving 3.txt.
PS C:\Users\administrator.HOMELAB> del .\1.txt
PS C:\Users\administrator.HOMELAB> del .\2.txt
PS C:\Users\administrator.HOMELAB> Get-ChildItem *.txt
Directory: C:\Users\administrator.HOMELAB
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 10/27/2013 7:12 PM 8 3.txt
Again place the result of get-childitem in a variable called txt and query the different elements in the array.
PS C:\Users\administrator.HOMELAB> $txt = Get-ChildItem *.txt
PS C:\Users\administrator.HOMELAB> $txt[0]
Unable to index into an object of type System.IO.FileInfo.
At line:1 char:6
+ $txt[ <<<< 0]
+ CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
+ FullyQualifiedErrorId : CannotIndex
This time an error is thrown. What happened?
The unable to index into an object of type System.IO.FileInfo line gives an important clue. We are dealing with a different type of object than before.
On this occasion get-childitem *.txt returns only one result which seems to cause the $txt variable to become a System.IO.FileInfo object.
PS C:\Users\administrator.HOMELAB> Get-Member -InputObject $txt
TypeName: System.IO.FileInfo
Name MemberType Definition
---- ---------- ----------
Mode CodeProperty System.String Mode{get=Mode;}
AppendText Method System.IO.StreamWriter AppendText()
CopyTo Method System.IO.FileInfo CopyTo(string destFileName), System.IO.FileInfo CopyTo(s...
[..removed for brevity..]
The solution is to enforce the creation of an array when creating $txt by using the following syntax:
PS C:\Users\administrator.HOMELAB> $txt = @(Get-ChildItem *.txt)
This time the $txt is a System.Object even when get-childitem returns only one result.
PS C:\Users\administrator.HOMELAB> Get-Member -InputObject $txt
TypeName: System.Object[]
Name MemberType Definition
---- ---------- ----------
Count AliasProperty Count = Length
Address Method System.Object&, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934...
Clone Method System.Object Clone()
[..removed for brevity..]
Querying elements in the array works as expected:
PS C:\Users\administrator.HOMELAB> $txt[0]
Directory: C:\Users\administrator.HOMELAB
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 10/27/2013 7:12 PM 8 3.txt
PS C:\Users\administrator.HOMELAB>
The lesson here is: if you expect the results in an array make sure you create an array.
p.s. Powershell V3 seems to handle this more graciously.