Share via


System.Collections.ArrayList problems when populated with one row

Question

Saturday, January 6, 2018 9:30 PM

I have a section of code that I have used many times in the past, and recently ran into an error. It is used to populate a list, to be used in a GUI dialog, for selection of an item in the list. I have never ran the code under the specific situation where only one item is returned from the function that populates the array. The function returns a collection of strings, but when it returns just one string, its type is just System.String, and it fails.

[System.Collections.ArrayList]$Widgets = (get-Widget).name

When get-Widget returns more than one item, the code works. When it returns only one item, it fails. 

Cannot convert the "Widget1" value of type "System.String" to type "System.Collections.ArrayList".
At C:\scripts\set-widgets.ps1:505 char:2
+     [System.Collections.ArrayList]$Widgets= (get-widget).nam ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException*
*    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException*

I assume I need to cast the return from Get-Widgets to something, but in all cases, or just if there is only one record returned?

Thanks,
David

All replies (3)

Saturday, January 6, 2018 9:37 PM ✅Answered | 1 vote

Simple solution.  An arraylist can only be initialized from an array.   Wrap it in an array and all results will work.

[System.Collections.ArrayList]$Widgets = @(get-Widget).name)

\(ツ)_/


Saturday, January 6, 2018 9:59 PM

See, this is what happens when you let a cut-and-paste, quick and dirty operations scripting try to write his own code. 

So, as I have often learned, when their is shorthand for something like this (using @ to cast results as an array) is there another method? I didn't see an '.ToArray' type of option, to post-pend.

Thanks,
David


Saturday, January 6, 2018 10:12 PM

This has nothing to do with casting.  We are simply using an array to wrap the results so a singleton can be assigned to any object that requires an array.  This is a very basic technique in PowerShell.  Most tutorials and books show this in thee first few chapters.

PS D:\scripts> $al = [collections.arraylist](Get-Process).Name
PS D:\scripts> $al = [collections.arraylist](Get-Process|select -first 1).Name
Cannot convert the "aesm_service" value of type "System.String" to type "System.Collections.ArrayList".
At line:1 char:1
+ $al = [collections.arraylist](Get-Process|select -first 1).Name
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException
# now wrap all results in an array.
PS D:\scripts> $al = [collections.arraylist]@((Get-Process|select -first 1).Name)
PS D:\scripts> $al = [collections.arraylist]@((Get-Process|select -first 10).Name)
PS D:\scripts>

Works every time.

You can cast a string, int or other singleton to an array:

[collections.arraylist]$x=[array](Get-Process).Name
[collections.arraylist]$x=[array](Get-Process | select -first 1).Name

The cast produces a slightly different type of array but works the same in this case.

\(ツ)_/