Powershell how to remove redundency in a n arraylist - powershell

I have the global arraylist "$global:processid", which has many processid-entries and $globale:processname, which has all the processes that belongs to the ids. sometimes all the entries the $global:processid arraylist got, are the same. how can i loop through the two arraylists and delete all duplicated processids and there processnames. I got the following code now. But i don't have this filtering.
[System.Collections.ArrayList]$global:processname = #()
[System.Collections.ArrayList]$global:processid = #()
for ($i = 0; $i -lt $global:processid.Count; $i++) {
"Position "+$i+": "+$global:processid[$i]
#$lvi = [System.Windows.Forms.ListViewItem]::new()
#$lvi.Text = $global:processname[$i]
#$lvi.SubItems.Add($global:processid[$i])
#$global:ListviewOCLRA.Items.Add($lvi)
}
It is important that the it will be checked for duplicated processids and delete the processnae at this position. For instance
if the positions 3-7 are the same entries again and again in the $global:processid arraylist, all the entries at positions 3-7 in the arraylist $global:processname should also be deleted.
I hope u understand what i mean. Thx for the help.

Although as commented, it would be best to use one single array containing objects, you can still create such an array using your two arraylists, as long as they are still intact and where each index can get you the id and a matching process name
Assume your arrays are like this:
$processid = 123, 456, 123
$processname = 'notepad', 'powershell', 'notepad'
As you can see, there's a duplicate in there
Join these arrays while their indices still match the name and id into one single array of objects
$processes = for ($i = 0; $i -lt $processid.Count; $i++) {
[PsCustomObject]#{ Id = $processid[$i]; Name = $processname[$i] }
}
Now you can eliminate the duplicate objects based on the ID property
$processes | Sort-Object -Property Id -Unique
$processes now contains:
ID Name
-- ----
123 notepad
456 powershell
Next, fill your listview
for ($i = 0; $i -lt $processes.Count; $i++) {
$lvi = [System.Windows.Forms.ListViewItem]::new()
$lvi.Text = $processes[$i].Name
$lvi.SubItems.Add($processes[$i].Id)
$ListviewOCLRA.Items.Add($lvi)
}

Related

for loop through 5 textboxes

I have created a GUI with 5 Textboxes. I call them $textboxHost1 - 5.
Now I have an array in which I'm gonna save up to 5 values and then write each value according to the order into the textboxes. The first value in the array should be written into the first $textboxHost1 box.
To do that, I would like to make a for loop and have written this code
#$hostnameneingabe: Array, in which the values are saved.
$hostnameneingabeCount = $hostnameneingabe.Count
for($i = 0; $i -le $hostnameneingabeCount; $i++) {
#code here
}
Now, I'm looking for a way to go down the order, so that the first $textboxHost1 comes firstly and so on.
To be accurate, the variable $textboxHost should be incrementally increased in the loop and the values at the position $i in the array should be written into that textbox.
sth like
for($i = 0; $i -le $hostnameneingabeCount; $i++) {
$textboxHost$i =
}
I suppose you would be liking something like this?
$textboxHosts = Get-Variable | ? {$_.Name -match "textBoxHost[0-9]" -and $_.Value -ne $null} | sort Name
After this you can process that var with eg. a foreach:
foreach ($textboxHost in $textboxHosts) {<# Do some stuff #>}
You have to use an array, because otherwise you can't loop through them:
$textboxHost = #(0..4)
#Textbox 0
$textboxHost[0] = New-Object System.Windows.Forms.TextBox
$textboxHost[0].Text = "test"
#Textbox 1
$textboxHost[1] = New-Object System.Windows.Forms.TextBox
$textboxHost[1].Text = "test"
foreach ($textbox in $textboxHost){
#Do whatever you want with the textbox
$textbox =
}

Enumerate through array fails

I'm enumerating through all of the datastores in our VMware environment to get names and used space.
When I run the foreach loop, it's both enumerating through the array, and not enumerating through the array.
Here's my script:
$list = #()
$row = '' | select Name, UsedSpace
$datastores = Get-Datastore
foreach ($store in $datastores) {
$row.name = $store.name;
$row.usedspace = [math]::Round(($store.extensiondata.summary.capacity - $store.extensiondata.summary.freespace)/1gb)
Write-Host $row; #To Verify that each row is different, and that enumeration is working#
$list += $row;
}
Console Output:
#{name=datastore1; usedspace=929}
#{name=datastore2; usedspace=300}
#{name=datastore3; usedspace=400}
$list variable output:
Name Usedspace
Datastore3 400
Datastore3 400
Datastore3 400
So it's enumerating through. getting all the correct data. but for some reason the line $list += $row is waiting until the last object in the array, grabs only that data, but knows that there's 3 objects in the array, and populates each index with that objects data.
The only thing I've done to troubleshoot is bounced my PowerShell console.
The reason for this is that $row is a single object. You created it once, and then you keep changing the values of its properties. When you add it to the array, you're adding a reference to it, not a copy. So the values seen will always be those that were most recently set.
Recreate your $row on every iteration of the loop.
Alternatively you could create a PSCustomObject
$list = foreach ($store in Get-Datastore) {
[PSCustomObject]#{
Name = $store.name
UsedSpace = [math]::Round(($store.extensiondata.summary.capacity -
$store.extensiondata.summary.freespace)/1gb)
}
}
$list
As mentioned in the comments, with:
$row = '' | select Name, UsedSpace; $row.GetType()
you implicitly also create an (empty) PSCustomObject,
but as this needs to be created in every iteration of the foreach and then (inefficiently) appended to $list by rebuilding the array - directly building the PSCustomObject is IMO more clear / straight forward.

Assigning values from one array to another in Powershell without encountering null index when de-referencing elements

I have an array with fields (a multi dimensional array, if I am correct), my aim is to create another array based on elements filtered from the first.
However when I come to deference $arr2 by looking at its first element $arr[0], I get the error message:
Cannot index into a null array
Can someone please provide me with some advise as to the most elegant way of resolving this.
for ($i=0; $i -lt $arr1.length; $i++) {
if ($arr1[$i].source -eq $SomeValue) {
$arr2 += #( $arr1[$i] )
}
}
$arr2 = #( $arr1 | Where { $_.source -eq $someValue } )

Iterating over several GUI elements

I have a GUI based form with a series of fields on it and want to update the corresponding label when text is entered into one field. I've been able to get it to work using the following code
$objTextBoxRD1.add_keyup({$objLabelLU1.Text = Get-Date})
$objTextBoxRD2.add_keyup({$objLabelLU2.Text = Get-Date})
$objTextBoxRD3.add_keyup({$objLabelLU3.Text = Get-Date})
$objTextBoxRD4.add_keyup({$objLabelLU4.Text = Get-Date})
Is there a more elegant way to achieve the same result?
I tried the following but when I enter text into any $objTextBoxRD fields it only updates $objLabelU4.
$Count = 1
foreach ($User in $ISDept) {
$objTextBoxRD = Get-Variable -Name ('objTextBoxRD' + ([string]$Count)) | Select -Expand Value
$objLabelLU = Get-Variable -Name ('objLabelLU' + ([string]$Count)) | Select -Expand Value
$objTextBoxRD.add_keyup({$objLabelLU.Text = Get-Date})
$Count++
}
The $objTextBoxRD and $objLabelLU variables have been generated from arrays and would like to automate this section as the number of variables that get created can vary.
Collect your textbox elements in an array instead of using individual variables, so you can iterate over them with a for loop. Since you want to use corresponding variables in a scriptblock you probably need to generate that scriptblock, though. Try this:
for ($i=0; $i -lt $objTextBoxRD.Count; $i++) {
$sb = [scriptblock]::Create("`$objLabelLU$($i+1).Text = Get-Date")
$objTextBoxRD[$i].Add_Keyup($sb)
}

Creating dynamic variable array names and then adding object to them

What I'm trying to do is create array variable names dynamically, and then with a loop, add the object to its relevant array based on the hash table value being equal to the counter variable.
$hshSite = #{} # Values like this CO,1 NE,2 IA,3
$counter = $hshSite.count
For($i = $counter; $i -gt 0; $i--) {
New-Variable -Name "arr$i" -Value #()
}
If $counter = 3, I would create arrays $arr1, $arr2, $arr3
$csv = Import-CSV....
ForEach ($x in $csv) {
#if $hshSite.Name = $x.location (ie CO), look up hash value (1),
and add the object to $arr1. If $hshSite.Name = NE, add to $arr2
I tried creating the dynamic arrays with New-Variable, but having issues trying to add to those arrays. Is it possible to concatenate 2 variables names into a single variable name? So taking $arr + $i to form $arr1 and $arr2 and $arr3, and then I can essentially just do $arr0 += $_
The end goal is to group things based on CO, NE, IA for further sorting/grouping/processing. And I'm open to other ideas of getting this accomplished. Thanks for your help!
Just make your hash table values the arrays, and accumulate the values to them directly:
$Sites = 'CO','NE','IA'
$hshSite = #{}
Foreach ($Site in $Sites){$hshSite[$Site] = #()}
ForEach ($x in $csv)
{
$hshSite[$x.location] += <whatever it is your adding>
}
If there's a lot of entries in the csv, you might consider creating those values as arraylists instead of arrays.
$Sites = 'CO','NE','IA'
$hshSite = #{}
Foreach ($Site in $Sites){ $hshSite[$Site] = New-Object Collections.Arraylist }
ForEach ($x in $csv)
{
$hshSite[$x.location].add('<whatever it is your adding>') > $nul
}
You could quite easily do add items to a dynamically named array variable using the Get-Variable cmdlet. Similar to the following:
$MyArrayVariable123 = #()
$VariableNamePrefix = "MyArrayVariable"
$VariableNameNumber = "123"
$DynamicallyRetrievedVariable = Get-Variable -Name ($VariableNamePrefix + $VariableNameNumber)
$DynamicallyRetrievedVariable.Value += "added item"
After running the above code the $MyArrayVariable123 variable would be an array holding the single string added item.