Reputation: 11
I am attempting to use multiple arrays to pass multiple server names, and maybe other elements, that maybe be needed in conjunction to each other to a function's set of Parameters in a Powershell function. While using a single loop, if that is even possible.
I wanted to script this process so you could pass an array via a parameter as a larger function to the 2nd function but use arrays. Instead of nested Hashtable.
This is similar to what i was attempting to do but I cant seem to get the arrays to pass each element one at a time for each respective array.
This is what I have gotten to get a "similar" result but I will not work if I have to have the index position via the [0].
$servers1 = @('serv1-01','serv1-02')
$servers2 = @('serv2-01','serv2-02')
$collectionItems = @()
$temp = New-Object System.Object
$temp | Add-Member -MemberType NoteProperty -Name "Server1" -Value $servers1
$temp | Add-Member -MemberType NoteProperty -Name "Server2" -Value $servers2
$collectionItems += $temp
Write-Host "Server1 is $($item.Server1[0]) and Server2 is $($item.Server2[0])"
foreach ($item in $collectionItems)
{
Write-Host "Server1 is $($item.Server1) and Server2 is $($item.Server2)"
}
#### This is the output if you run the above script#####
Server1 is serv1-01 and Server2 is serv2-01
Server1 is serv1-01 serv1-02 and Server2 is serv2-01 serv2-02
Below is kind of the skeleton of what i am trying to accomplish... I know that you can have a nested Hashtable that uses one of the Key:Value pairs as an array, but im not sure if you can pass that in at the commandline as a nested Hashtable or how that would work to use the params to add to the nested sections of the Hashtable vs keeping this hashtable up to date ((Which would not be ideal))
I know the code below will not work but its the best visual representation of my desired end goal
function Bigger-ServerListAdding {
#List of servers to add some config too
$servers1 = @('serv1-01','serv1-02')
$servers2 = @('serv2-01','serv2-02')
#This variable can be passed in and fixed with a -join ',' as a comma separated list
$componentlist = @('sister','brother','uncle','mom','dad')
###This section should do each element not the entire array list being passed###
foreach (item in $somecollection){
Set-TheseServersOnaConfig -Server1 $item.servers1 -Server2 $item.servers2 -ComponentList $($componentlist -join ",")
}
}
Mind you this is like he 2nd question i've ever asked on StackOverflow. Any suggestions as this type of thing in the future.
Thank you very much!
Upvotes: 1
Views: 3747
Reputation: 1166
Powershell's handling of multi-dimensional arrays is pretty lousy, and I try to avoid using them any chance I get. Jawad's answer in the comments, to create an array of HashTables, is one way of avoiding using them, but it doesn't take advantage of PowerShell's object oriented nature. As an example, I want to pass information about 3 computers, their names, HD Size, and Memory Size. Using the HashTable solution, you get:
$Array = @()
$Array += @{Computer='star';HD='2TB';Memory='16GB'}
$Array += @{Computer='comet';HD='1TB';Memory='8GB'}
$Array += @{Computer='meteor';HD='3TB';Memory='16GB'}
This array contains 3 items:
PS> $Array.Count
3
And you can access the data as you would expect:
PS> $Array[1]['Computer']
comet
But you can also access it as a property.
PS> $Array[1].Computer
comet
But, when you list the contents, the data is intermingled, and not easy to understand:
PS> $Array
Name Value
---- -----
Memory 16GB
HD 2TB
Computer star
Memory 8GB
HD 1TB
Computer comet
Memory 16GB
HD 3TB
Computer meteor
And further, the "fields" you have created are not properties of the object, but are members of the keys array, and are more difficult to iterate through than they need to be.
PS C:\Users\Matthew> $Array[0] | gm
TypeName: System.Collections.Hashtable
Name MemberType Definition
---- ---------- ----------
Add Method void Add(System.Object key, System.Object value), void IDictionary.Add(System.Object key, S...
Clear Method void Clear(), void IDictionary.Clear()
Clone Method System.Object Clone(), System.Object ICloneable.Clone()
Contains Method bool Contains(System.Object key), bool IDictionary.Contains(System.Object key)
ContainsKey Method bool ContainsKey(System.Object key)
ContainsValue Method bool ContainsValue(System.Object value)
CopyTo Method void CopyTo(array array, int arrayIndex), void ICollection.CopyTo(array array, int index)
Equals Method bool Equals(System.Object obj)
GetEnumerator Method System.Collections.IDictionaryEnumerator GetEnumerator(), System.Collections.IDictionaryEnu...
GetHashCode Method int GetHashCode()
GetObjectData Method void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Seri...
GetType Method type GetType()
OnDeserialization Method void OnDeserialization(System.Object sender), void IDeserializationCallback.OnDeserializati...
Remove Method void Remove(System.Object key), void IDictionary.Remove(System.Object key)
ToString Method string ToString()
Item ParameterizedProperty System.Object Item(System.Object key) {get;set;}
Count Property int Count {get;}
IsFixedSize Property bool IsFixedSize {get;}
IsReadOnly Property bool IsReadOnly {get;}
IsSynchronized Property bool IsSynchronized {get;}
Keys Property System.Collections.ICollection Keys {get;}
SyncRoot Property System.Object SyncRoot {get;}
Values Property System.Collections.ICollection Values {get;}
However, if you were to take advantage of the Object nature of PowerShell, and instead of HashTables, use a PowerShell Custom Object (Type [PSCustomObject]), that changes dramatically. You can create a new object in many ways, but you can check out this TechNet Article PowerShell: Creating Custom Objects for a bunch of them. I'm going to use my personal favorite, which is extremely similar to the HashTable method, as it uses a HashTable to define the object parameters:
$Array = @()
$Array += [PSCustomObject]@{Computer='star';HD='2TB';Memory='16GB'}
$Array += [PSCustomObject]@{Computer='comet';HD='1TB';Memory='8GB'}
$Array += [PSCustomObject]@{Computer='meteor';HD='3TB';Memory='16GB'}
This gives you the same 3 items in the array:
PS> $Array.Count
3
Since the data is not in HashTable format, you can't access it like a HashTable, but you can access it like a property:
PS> $Array[1]['Computer']
PS> $Array[1].Computer
comet
But what you gain is that the data is kept separately in distinct objects:
PS> $Array
Computer HD Memory
-------- -- ------
star 2TB 16GB
comet 1TB 8GB
meteor 3TB 16GB
And the definition of the object is nice and neat:
PS> $Array[0] | gm
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Computer NoteProperty string Computer=star
HD NoteProperty string HD=2TB
Memory NoteProperty string Memory=16GB
I hope this assists you in understanding more about how PowerShell handles data, and helps you make the right choices for how to store yours.
Upvotes: 1