Find value in array of objects after importing from CSV file - powershell

I am reading in values from a CSV file using Import-Csv which include server name, ip address and a note field
Is there a built in mechanism to find an object based on the server name without having to loop through the entire array?
I'm keeping the array in memory to use multiple times.
$ServerList = Import-Csv ".\ServerList.csv"
I'm creating a GUI with Powershell Studio and populating a dropdown with all the server names read in from the file. The user will choose a server from the dropdown and there will be buttons to perform actions on that server using the IP address read in.

You could populate a hashtable with the data from the CSV, using the servername as key:
$ServerList = #{}
Import-Csv '.\ServerList.csv' | % { $ServerList[$_.ServerName] = $_ }
That way you can access the data like this:
$server = 'foo'
$ServerList[$server].IPAddress

$csv = Import-csv my.csv | where {$_.servername -eq "MyServer"}
foreach ($server in $csv) {
# Do your thing
}

If you need to call it multiple times you can use a function that you call when the user selects a server:
function getServer($selectedServer){
$ServerInfo = Import-Csv ".\ServerList.csv" | where {$_.servername -eq $selectedServer}
return $ServerInfo
}
When the user makes a selection the code would like like so:
$Server = getServer('ABCSRV')
Then $Server.IP and $Server.Notes would have the information from that specific server, granted that you have these columns in place in your csv.

Related

Powershell - Compare CSV 1 to CSV 2 and then update CSV1

I am not looking for a writing service but please can someone point me in the right direction as I am completely at a lost as to how to proceed.
Overview
I have a CSV which contains a lot of data, some of which comes from a script and some in manually imputed. I can run the script and get new data which is good. What I would like to do is find a way to compare the orginal CSV 1 to the new CSV 2 and update CSV 1.
Code I currently have
$Vips_to_check = #{}
Import-Csv 'C:\Users\user\Documents\20221201\Netscaler VIPs per Cluster_edited - Raw Data.csv' |
Where-Object {$_.PRD -match "No PRD code from VIP IP and VIP has no backend IPs" -or
$_.PRD -match "No PRD code found from VIP or backend IPs" -or
$_.PRD -match "No PRD code found from backend IPs" -and
$_.ipv46 -notcontains "0.0.0.0"} |
$Results_from_PIM = Import-Csv 'C:\Users\user\Documents\20221201\VIP-Owners_edited.csv'
Both of the CSV's have the same headers and layout which is good. I assume!
CSV 1
Name IPV46 Port Curstate Suggested PRD Display Name tech Owner Slack Channel Support Email
name 1 1.2.3.4 8080 Down No No No No No No No
CSV 2
Name IPV46 Port Curstate Suggested PRD Display Name tech Owner Slack Channel Support Email
name 1 1.2.3.4 8080 Down No PRD123 TMOL Gary TMOL Support Support#email.com nsr.sys
I would guess at creating a hashtable but I just can't seem to get my head around the format of them. I tried
$ht = $Results_from_pim #{}
$_.Name = (cant figure out how to reference the cell)
$_.PRD =
$_.("Display Name")
$_.("Tech Owner")
Once I have the data in the hash table how do I overwrite the CSV 1 data?
Any points or guides would be great. I have tried reading up on https://learn.microsoft.com/en-gb/powershell/scripting/learn/deep-dives/everything-about-hashtable?view=powershell-7.3 and https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-pscustomobject?view=powershell-7.3
But that left me even more confused.
At the moment the difference is only 4 or 5 entries and it would of been quicker for me to manually edit in excel but as this script gets larger I can see it being more time consuming to do manually.
As always thank you.
UPDATE
$ht = #{}
foreach ($item in $Results_from_PIM) {
"name = $($item.name)"
"prd = $($item.PRD)"
"Display Name = $($item.'Display Name')"
"Tech Owner = $($item.'Tech Owner')"
"Slack Channel = $($item.'Slack Channel')"
"Support Email = $($Item.'Support Email')"
}
I have created the hash table that I wanted from the CSV 2. Just got to get it to compare to CSV 1.
Update 2
Further to #theo request I have adjusted the question. Also to clarify When I want to merge the CSV it is based on matching the Name, IPV46 and Port on both CSV and then moving the updated data from CSV2 into CSV1.
You can do that with the code below (no extra module needed):
$csv1 = 'C:\Users\user\Documents\20221201\Netscaler VIPs per Cluster_edited - Raw Data.csv'
$csv2 = 'C:\Users\user\Documents\20221201\VIP-Owners_edited.csv'
$Results_from_PIM = Import-Csv -Path $csv2
$newData = Import-Csv -Path $csv1 | ForEach-Object {
$search = $_.Name + $_.IPV46 + $_.Port # combine these fields into a single string
$compare = $Results_from_PIM | Where-Object { ($_.Name + $_.IPV46 + $_.Port) -eq $search }
if ($compare) {
# output the result from csv2
$compare
}
else {
# output the original row from csv1
$_
}
}
# now you can save the updated data to a new file or overwrite csv1 if you like
$csv3 = 'C:\Users\user\Documents\20221201\VIP-Owners_Updated.csv'
$newData | Export-Csv -Path $csv3 -NoTypeInformation
P.S. Please read about Formatting
After being direct to In PowerShell, what's the best way to join two tables into one? by #jdweng. I performed the following which seems to have meet my requirements
Install-Module -Name JoinModule -Scope CurrentUser
$Vips_to_check = Import-Csv 'C:\Users\user\Documents\20221201\Netscaler VIPs per Cluster - Raw Data.csv'
$Results_from_PIM = Import-Csv 'C:\Users\user\Documents\20221201\VIP-Owners.csv'
$Vips_to_check | Update-Object $Results_from_PIM -On name, Ipv46, port | Export-Csv 'C:\Users\user\Documents\20221201\Final_data1.csv'
Going to do further testing with larger data sets but appears to work as required.

Foreach loops Always runs the last object results

I'm still new with the powershell, there's a questions with my script, my intention is to import the CSV data under column Name
then do a split() for each object with "computername" and "username", however it can catch the arrays with two results, but after the loop in Foreach it only runs the last object. Can someone help Thanks!
whole code
$ImportPath ="C:\data.csv"
$ComputerArray= #()
Import-Csv -Path $ImportPath |ForEach-Object{$ComputerArray+= $_.Name}
Foreach($Hostname in $ComputerArray){
$CharArray =$Hostname.Split("\")
$ComputerName = $CharArray[0]
$Username = $CharArray[1]
}
CSV date looks like
CSV data
$ComputerArray results
----------------------
Computer1\Local User
Computer2\Remote User
Hopes to look like
$ComputerName results
---------------------
Computer1
Computer2
$Username results
---------------------
Local User
Remote User
It's not running the last object only, it's running all the objects but you're only capturing the last one. Both variables $computerName and $userName are getting re-assigned on each iteration.
Below will give you an array of objects with the Computer and User properties for each line of your CSV.
$ImportPath = "C:\data.csv"
$ComputerArray = (Import-Csv -Path $ImportPath).Name
$result = foreach($Hostname in $ComputerArray)
{
$ComputerName, $Username = $Hostname.Split("\")
[pscustomobject]#{
Computer = $ComputerName
User = $Username
}
}
$result | Format-Table
If you want to get the computers on one array and the users on other array like in your expected output you can do $result.Computer and $result.User.

Powershell CSV-Export with PSCustomObject

I have a script with which I'm collecting data about users like this:
$testObject = [PSCustomObject]#{
username = $username
name = $name
}
Next, I'm getting more info and add to testObject like this:
$testObject | Add-Member address address
At the end I'm exporting it to csv:
$testObject | Export-Csv -Path "output.csv" -NoTypeInformation
I need to change the script so the creation of the testObject is in a loop since I will run it for a list of users.
How can I write this to create a new csv when the script starts, but append all new objects?
I'm trying to avoid creating an array of PSCustomObject since I'm using the script on large amount of data and I would prefer to write one object at a time to the csv.

Compare-Object with variables containing different properties

I'm in the middle of writing a script that finds inconsistensis of the servers in our infrastructure. Basicly what i do is source the Name and status of our servers from 2 different sources and find missmatches. Source 1 is our SQL with the properties Name and Status (status can be either InUse or Removed) Source 2 is from vCenter with properties Name and PowerState (PoweredOn or PoweredOff) These are then stored in different variables,
Using this info i'd like to compare Status and PowerState of each server, InUse and PoweredOn should match and be outputted to null while all others (for ex InUse and PoweredOff) should not match and be outputted to a table or csv along with the servername for further investigation.
I tried renaming the properties to the same name and then filtering them with ForEach but i canĀ“t quite get it to work.
Any help is appreciated.
Assumptions:
You're using PowerShell
I'm assuming that you know how to fetch the lists into a dictionary. For sake of ease, I'll assume you're using hashtables.
I'm assuming that the names of the servers are exactly the same in both sources. If not, you will need to account for this in your script (lookup table perhaps) or adjust the names in one source.
$sqllist is the list from SQL, keyed by name
$vclist is the list from vCenter, keyed by Name
$output = #()
foreach ($serversql in $sqllist)
{
$entry = $null
$servervc = $vclist.Get($serversql.Name)
if ($serversql.Status -match 'InUse' `
-and $servervc.PowerState -match 'PoweredOn')
{
$entry = [PsCustomObject]#{
Name=$serversql.Name
SqlStatus=$null
vCenterStatus=$null
}
} else
{
$entry = [PsCustomObject]#{
Name=$serversql.Name
SqlStatus=$serversql.Status
vCenterStatus=$servervc.PowerState
}
}
}
$output | Export-CSV -Path log.csv

Create Variables from CSV

I have a script that I want to import a CSV and create separate variables. One for WindowsKey and the other for OfficeKey
CSV Will look like:
School, WindowsKey, OfficeKey
Saints, BBBB-BBBB, XXXX-XXXX
Bears, YYYY-YYYY, ZZZZ-ZZZZ
Part of the Script:
$School = "Saints"
(Import-Csv k:\Keys.csv) | Where-Object {$_.School -eq $School}
This will make a table that looks like this:
School : Saints
WindowsKey: BBBB-BBBB
OfficeKey : XXXX-XXXX
How do I go about putting WindowsKey and OfficeKey into a variable that I can use later on in the script?
You can do it like this:
$csv = Import-Csv k:\keys.csv | Where-Object {$_.School -eq $School}
then you can access the data by dot notation, for example
$csv.WindowsKey
note that the properties contain arrays and not string data if you select multiple values so you will have to loop through it
Regards
Another approach (if you want to be able to access all keys by school) would be to create 2 hashtables for Windows and Office keys:
$csv = Import-Csv 'K:\Keys.csv'
$windowsKeys = #{}
$officeKeys = #{}
$csv | % {
$windowsKeys[$_.School] = $_.WindowsKey
$officeKeys[$_.School] = $_.OfficeKey
}
Then you can access the keys for each school like this:
$school = 'Bears'
"Windows Key ({0}): {1}" -f $school, $windowsKeys[$school]
"Office Key ({0}): {1}" -f $school, $officeKeys[$school]