Array and For loop for in Powershell - arrays

I am having two variables as below
$IP=#("IP1","IP2","IP3")
$Hostname=#("Host1","Host2","Host3")
I am working on some project in which there is Combobox and if the user selected the first choice then there is some command which should take variable as first IP and first hostname and when user select "ALL-DC" option, the command should be running on every IP and hostname one by one.
I am using below code
if ($Unity_ComboBox.text -match 'unit-02') {
$Unity=$IP[0]
$show=$hostname[0]
} elseif ($Unity_ComboBox.text -match 'zone-03'){
$Unity=$IP[1]
$show=$hostname[1]
} elseif ($Unity_ComboBox.text -match 'site-04'){
$Unity=$IP[2]
$show=$hostname[2]
} elseif ($Unity_ComboBox.text -match 'ALL DC'){
$Unity=$IP
$show=$hostname
}
foreach ($u in $Unity){
echo $u
echo $show
}
In individual its working fine but in case of ALL DC it's messing up with $show.
Could someone suggest me some better way to achieve this?

A one-liner using a better regex:
if($Unity_ComboBox.text-match".*DC-0([2-4]).*"){$Unity=$IP[$matches[1]-2];$show=$Hostname[$matches[1]-2]}elseif($Unity_ComboBox.text-match"ALL DC"){$Unity=$IP;$show=$Hostname}
Here the first regex is .*DC-0([2-4]).* capture the last computer index. If your form takes only the names nothing more then change it to ^DC-0([2-4])$.
Then assign two variables using the match.
If not, do the else

Related

How do I set the binding port number for a set of IIS websites with an increment value using PowerShell?

I have an IIS back end server with many websites. I just created these sites using powershell. I need to set the binding port for each website to a unique number (starting at 9200) for the proxy. I am trying to find a way to script this out, but I am having a hard time trying to find a solution to this one. Currently I have a list of websites in a text file I want to set the binding port for. Right now this is what I have:
Import-Module WebAdministration
$endpoints = Get-Content C:\scripts\endpoints.txt
foreach ($number in 9200..9310)
{
foreach ($site in $endpoints)
{
Set-WebBinding -Name '$site' -BindingInformation "*:80:" -PropertyName Port -Value $number
}
}
The reason I have the first foreach loop is to get the port numbers from 9200-9310 since I have 110 websites in total. Am I going about this the wrong way?
It seems the issue is your two foreach loops. You have your second foreach loop inside of the one containing the port numbers. Therefore, your first loop starts at $number = 9200 and then sets EACH $site equal to the port held in your $number variable at that time and then exits that loop and increments the port number and starts again.
Here is something I came up with that I believe will solve your problem.
Import-Module WebAdministration
$endpoints = Get-Content C:\scripts\endpoints.txt
$ports = New-Object System.Collections.ArrayList
[int] $port = 9200
[int] $counter = 0
while($port -le 9310) {
$ports.Add($port)
$port++
}
foreach ($site in $endpoints)
{
Set-WebBinding -Name '$site' -BindingInformation "*:80:" -PropertyName Port -Value $ports[$counter]
$counter++
}

Powershell: Comparing a value between two arrays, and extracting a related value

so here is what I'm trying to accomplish.
I have a form for a new starter, New Starter Form.csv, that has the following headers and information:
firstname,lastname,teamname,startdate
Joe,Bloggs,Security Admin,01/01/18
I have a different csv called Team List.csv, that has the following headers and information:
teamlead,teamname,resgroup
A B,Marketing,RESMARKETING01G
C D,Product,RESPRODUCT01G
E F,Advertising,RESADVERTISING01G
G H,Security Admin,RESSECURITYADMIN01G
I want to import both CSV files into Powershell, run a comparisson that takes the team name from the New Starter Form, and checks if there are any matches in the Team List, and if so, add the relevant RES group to the new starter in AD.
Currently, I can import them, compare them, find a match, and find an index number for the record, but I'm struggling to the take this index number, and use it to get the relevant RES group. So far the code looks like this:
$teamlist = import-csv "\\location\Team List.csv"
$newstarter = import-csv "\\otherlocation\New Starter Form.csv"
[string]$teamname = Compare-Object -includeequal -excludedifferent -PassThru $newstarter.teamname $teamlist.teamname
$teamname
[array]::indexof($teamlist,$teamname)
And running that, provides us with this in the console, showing that we can indeed see the match, and that the matching record is the last (-1) one:
PS C:\WINDOWS\system32> $teamlist = import-csv "\\location\Team List.csv"
$newstarter = import-csv "\\otherlocation\New Starter Form.csv"
[string]$teamname = Compare-Object -includeequal -excludedifferent -PassThru $newstarter.teamname $teamlist.teamname
$teamname
[array]::indexof($teamlist,$teamname)
Security Administration
-1
I've not got a lot of experience with Powershell, and my coding knowledge is pretty limited overall, but I'm used to the concept that I can save the index value as a variable, and then I could call that variable back to do something like $teamlist.resgroup[VARIABLE HERE].
But if I try and declare a new variable before [array]::indexof($teamlist,$teamname), Powershell isn't happy.
Whilst I've not looked into it, I believe a possible alternative could be to add in a huge switch statement, but I may be looking at having 100+ teams overall, and I'd like to avoid inefficient code wherever I can. Am I missing something obvious though? Is there a better way (Or even just a functioning way would be great!) that this could work?
Any help you can provide would be greatly appreciated!
$teamlist = import-csv "\\location\Team List.csv"
$newstarter = import-csv "\\otherlocation\New Starter Form.csv"
# get a single new starter
$person = $newstarter | Where-Object { $_.firstname -eq 'Joe' -and $_.lastname -eq 'Bloggs' }
# get the new starters team
$team = $teamlist | Where-Object { $_.teamname -eq $person.teamname }
# get the new starters resource group
$resgroup = $team.resgroup
# use the resource group - this simply writes it to the console
Write-Host $resgroup
The code above will:
import your two csvs
grab a single new starter from your new starter csv, based on first &
last name
grab the team & resource group for that new starter from the team list
display the resgroup (this is where you will need to use to populate AD)

How to save different file paths to multiple variables in powershell

I have a powershell form with a Browse button that is used to pick out a file and then the path to that file is saved into a textbox variable and displayed in the form. That part works fine, however, I have 3 text boxes that I'd like have filled in independently of each other, each with their own file path if the user decides to pick 3 different files. Make sense?
Here's the code...
[void][System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
[void]$OpenFileDialog.ShowDialog()
If ($networktext1.Text -eq "") { $networktext1.Text = $OpenFileDialog.FileName }
If ($networktext2.Text -eq "") { $networktext2.Text = $OpenFileDialog.FileName }
If ($networktext3.Text -eq "") { $networktext3.Text = $OpenFileDialog.FileName }
If (($networktext1.Text -ne "") -and ($networktext2.Text -ne "") -and ($networktext3.Text -ne "")) { $logbox.Items.Add(" ERROR: No network slots available") }
I've played around with it every way I can think of and I can't get it to only fill in the first box, or if that one is taken only fill in the second box and so on. Obviously the code above will fill in all 3 boxes the first time a file is chosen and then give the error that they're all full. I brought it back to that point so it'd be easier to follow and modify with possible solutions.
Thanks!

Why can't I lookup an array index inside a foreach loop in Powershell?

first question on here so forgive me if I make any mistakes, I will try to stick to the guidelines.
I am trying to write a PowerShell script that populates two arrays from data I read in via CSV file. I'm using the arrays to cross-reference directory names in order to rename each directory. One array contains the current name of the directory and the other array contains the new name.
This all seems to be working so far. I successfully create and populate the arrays, and using a short input and index lookup to check my work I can search one array for a current name and successfully retrieve the correct new name from the second array. However when I try to implement this code in a foreach loop that runs through every directory name, I can't lookup the array index (it keeps coming back as -1).
I used the code in the first answer found here as my template.
Read a Csv file with powershell and capture corresponding data . Here's my modification to the input lookup, which works just fine:
$input = Read-Host -Prompt "Merchant"
if($Merchant -contains $input)
{
Write-Host "It's there!"
$find = [array]::IndexOf($Merchant, $input)
Write-Host Index is $find
}
Here is my foreach loop that attempts to use the Index lookup, but returns -1 every time. However I know it's finding the file because it enters the if statement and prints "It's there!"
foreach($file in Get-ChildItem $targetDirectory)
{
if($Merchant -contains $file)
{
Write-Host "It's there!"
$find = [array]::IndexOf($Merchant, $file)
Write-Host Index is $find
}
}
I can't figure it out. I'm a PowerShell newb so maybe it's a simple syntax problem, but it seems like it should work and I can't find where I'm going wrong.
Your problem seems to be that $Merchant is a collection of file names (of type string), whereas $file is a FileInfo object.
The -contains operator expects $file to be a string, since $Merchant is a string array, and works as you expect (since FileInfo.ToString() just returns the file name).
IndexOf() isn't so forgiving. It recognizes that none of the items in $Merchant are of the type FileInfo, so it never finds $file.
You can either refer directly to the file name:
[array]::IndexOf($Merchant,$file.Name)
or, as #PetSerAl showed, convert $file to a string instead:
[array]::IndexOf($Merchant,[string]$file)
# or
[array]::IndexOf($Merchant,"$file")
# or
[array]::IndexOf($Merchant,$file.ToString())
Finally, you can call IndexOf() directly on the array, no need to use the static method:
$Merchant.IndexOf($file.Name)

Index is out of range powershell

I have a script that builds a GUI with a list of printers that will be selected by the user.
These printers are also on a CSV file built like this :
Computer (name of the printer); IP
xxxx;x.x.x.x
I want to collect all the selected values in an array named x
Then I want to take every entry in the CSV that corresponds to the selected item and put it in another array named y
Finally I export the y array into a new CSV that will be used to install the printers on the domain.
I tried to go straight from second step to last step but i couldn't.
Here is the part of the code :
$OKButton.Add_Click({
foreach ($objItem in $objListbox.SelectedItems)
{$x += $objItem}
y=#()
for ($i=0; $i -lt $x.length; $i++)
{
$y[$i]=Import-Csv C:\Users\Administrateur\Desktop\Classeur33.csv | Where-Object {$_.Computer -eq $x[$i]}
}
$y > C:\Users\Administrateur\Desktop\allezjoue.csv
I've tried to do it with a 3 values x array in another script and it worked fine, but I really need to keep the listbox that allows the user to select the printers he wants.
Powershell always returns me "Index out of range"
I tried to put "$y=$x" so they have the same range, but when I do this it returns that I can't index in an object which has "System.string" type.
This is PowerShell and very object oriented. Use the objects and collections at hand.
Decriptive variable names are your friend.
$objListbox.SelectedItems is already a collection of objects.
Put it in a variable and loop through it with Foreach-Object aka foreach.
Import-CSV returns a collection of objects.
$Selection = $ObjListbox.SelectedItems
$printers = Import-CSV 'C:\Users\Administrateur\Desktop\Classeur33.csv'
foreach ($chosen in $Selection) {
$printers = $printers | where-object { $_.Computer -eq $Chosen.Name }
}
$printers | Export-CSV 'C:\Users\Administrateur\Desktop\allezjoue.csv' -NoTypeInformation
$Chosen.Name should be edited to conform with whatever objects you get in $Selection. You can test this by $ObjListbox.SelectedItems | Get-Member and examining the members for a property with the name of the item selected, then assuming the names match what's in your CSV, you should be good.
(bonus note) Storing data in and running as local admin is bad practice, even on your home lab. Your mistakes will have the power of local admin, and your users will not be able to run the scripts since the source/results files are in admin's desktop.

Resources