for loop through 5 textboxes - powershell

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 =
}

Related

Powershell how to remove redundency in a n arraylist

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

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

Unable to iterate through e-mail objects using powershell in Outlook

I'm writing a script, which takes Outlook folder as input and moves every unread mail to different folder. My code:
Add-Type -assembly "Microsoft.Office.Interop.Outlook"
$Outlook = New-Object -ComObject Outlook.Application
$namespace = $Outlook.GetNameSpace("MAPI")
$olFolderInbox = 6
$inbox = $namespace.GetDefaultFolder($olFolderInbox)
$myFolder = $namespace.pickfolder()
$toFolder = $inbox.Folders | where-object { $_.name -eq "UnreadMessages" }
$messages = $myFolder.Items
$messageCount = $messages.count
for ($i = $messageCount - 1; $i -ge 0; $i--)
{
if ($messages[$i].unread -eq $True)
{
$message.move($toFolder)
}
}
The problem is, that I can not iterate through "messages" objects. Error:
Unable to index into an object of type System.__ComObject.
If it's not possible, then how am I supposed to do it?
Thanks in advance.
EDIT. It's my first day using powershell :)
All Outlook collections are 1 based, not 0 - you need to iterate from Items.Count down to 1.
Secondly, do not just iterate through all messages in a folder, use Items.Find/FindNext. In your case, the search criteria would be "[Unread] = true".
Try to do a get-member on it, and see what your options are.
$Messages | Get-Member -force
If you figure out how you want to proceed, then you can use the ForEach-Object to loop through $Messages' content like this
$Messages | ForEach-Object { Script code }
Or use its abbreviation:
$Messages | % { Script code }
While you cannot use PowerShell's usual indexing syntax - $messages[$i] -
for accessing the elements of $messages, you can use .Items($i) on the folder object (see the docs):
Additionally, as noted in Dmitry Streblechenko's helpful answer, indices start at 1, not 0:
for ($i = $myFolder.Items.Count; $i -ge 1; $i--)
{
$message = $myFolder.Items($i)
if ($message.unread)
{
$message.move($toFolder)
}
}
For simple forward enumeration without indices you can use foreach:
foreach ($message in $myFolder.Items) {
if ($message.unread)
{
$message.move($toFolder)
}
}
($myFolder.Items | ForEach-Object { ... } should work too, but it will be slower.)
That said, Dmitry's answer answer also points to how to perform a filtered enumeration at the source, which performs much better.
Thanks for replying. All your answers were helpful. I finally used foreach loop. While I was trying to use $message = $myFolder.Items($i) following error appeared:
Method invocation failed because [System.__ComObject] doesn't cont
ain a method named 'Items'
so there is no possibility to iterate using indexes in this case.
Thank You all for your time :)

how to use a FOR loop variable to help define another variable

I am new to powershell scripts and not sure how to achieve the below:
$finalArray = #()
$tempArray0 = 'A'
$tempArray1 = 'B'
$tempArray2 = 'C'
FOR (i=0; i -eq 5; i++) {$finalArray += $tempArray[i]}
$finalArray
Output Should be:
A
B
C
If the variable name is itself variable, you'll have to use the Get-Variable cmdlet to retrieve its value:
$finalArray = #()
$tempArray0 = 'A'
$tempArray1 = 'B'
$tempArray2 = 'C'
for($i=0; $i -le 2; $i++) {
$finalArray += (Get-Variable "temparray$i" -ValueOnly)
}
$finalArray
If you want to create variables with variable names, use the New-Variable cmdlet:
$Values = 'A','B','C'
for($i = 0; $i -lt $Values.Count; $i++){
New-Variable -Name "tempvalue$i" -Value $Values[$i]
}
which would result in:
PS C:\> $tempvalue1
B
Although the above will solve the example you've presented, I can think of very few cases where you wouldn't be better of using a [hashtable] instead of variable variable names - they're usually an over-complication, and you'll end up with unnecessary code anyways because you need to calculate the variable names at least twice (during creation and again when reading the value).
From the comments, it sounds like you're trying to generate input for a password generator. This can be simplified grossly, without resorting to variable variable names:
# Create a hashtable and generate the characters
$CharArrays = #{
Letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray()
Numbers = 0..9
}
# Generate some letters for the password
$PasswordChars = $CharArrays['Letters'] |Get-Random -Count 10
# Generate a few digits
$PasswordChars += $CharArrays['Numbers'] |Get-Random -Count 4
# Shuffle them around a bit
$PasswordChars = $PasswordChars |Sort-Object {Get-Random}
# Create your password
$Password = $PasswordChars -join ''

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.