Adeel ASIF
Adeel ASIF

Reputation: 3534

Add column and assign value to an existing array

I want to add a column and a value to an existing array generated from a CSV.

This is my code:

$mycsv = "C:\Users\test\Documents\serveurs.csv"
$servers = Import-Csv $mycsv

This is the result:

ServerName                              Ip
----------                              --
Castor                                  172.22.0.64
Pollux                                  172.22.0.67

I want to add new column with value for each ServerName, like this:

ServerName                              Ip                  Available
----------                              --                  ---------
Castor                                  172.22.0.64         Yes
Pollux                                  172.22.0.67         No

I tried the code below:

$item = New-Object PSObject
$item | Add-Member -Type NoteProperty -Name 'Available' -Value 'Yes'

$servers += $item

But it's actually not working, can anyone help me?

The final idea is to have value assigned if the server is reachable or not over the network, using Test-Connection cmdlet.

Upvotes: 7

Views: 90753

Answers (4)

kovkov
kovkov

Reputation: 1

If you want to create your custom object and adding values this should be possible by doing something similar to this:

     [System.Collections.ArrayList]$myList = @()
     $mycsv = "C:\Users\test\Documents\serveurs.csv"
     $servers = Import-Csv $mycsv
     ForEach ( $server in $servers ) {
     $myobj = New-Object PSObject
     $test="No"
     if (Test-Connection $server.ip -Count 1 | Out-Null){
     $test="Yes"
     } 
     Add-Member -InputObject $myobj -NotePropertyName Name -NotePropertyValue $server.ServerName
     Add-Member -InputObject $myobj -NotePropertyName IP -NotePropertyValue $server.ip
     Add-Member -InputObject $myobj -NotePropertyName Available -NotePropertyValue $test
     $mylist.add($myobj)
     }$mylist

You will receive a list of your objects which you can then export into your csv or sort or anything

Upvotes: 0

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200313

You could use a calculated property for determining the availability of each server:

$csv1 = 'C:\Users\test\Documents\serveurs.csv'
$csv2 = 'C:\Users\test\Documents\serveurs2.csv'

Import-Csv $csv1 |
    Select-Object ServerName, Ip,
        @{n='Available';e={[bool](Test-Connection -Count 1 $_.Ip 2>$null)}} |
    Export-Csv $csv2 -NoType

Note, however, that even when limiting the test to a single probe per server this may take some time, since all items are processed sequentially. If you have a lot of servers to test, you may want to run the checks as parallel jobs:

$csv = 'C:\Users\test\Documents\serveurs.csv'

$servers = Import-Csv $csv

# clear job queue
Remove-Job *
# load job queue with test jobs
$servers | ForEach-Object {
    Start-Job -ScriptBlock {
        $args[0]
        [bool](Test-Connection -Count 1 $args[0] 2>$null)
    } -ArgumentList $_.Ip
}
# wait for jobs to finish
do {
    Start-Sleep -Milliseconds 100
} while (Get-Job -State 'Running')

# gather job results into hashtable
$availability = @{}
Get-Job | ForEach-Object {
    $result = Receive-Job -Id $_.Id
    $availability[$result[0]] = $result[1]
    Remove-Job -Id $_.Id
}

# add availability column to server data and export back to CSV
$servers |
    Select-Object ServerName, Ip, @{n='Available';e={$availability[$_.Ip]}} |
    Export-Csv $csv -NoType

Upvotes: 10

mjolinor
mjolinor

Reputation: 68283

Populating the field value aside, another option for getting the property added is to use Select-Object.

$csv = 'C:\Users\test\Documents\serveurs.csv'
$servers = Import-Csv $csv | select *,Availability

Then populate availability however you choose.

If you're going to use background jobs to multithread I think you'd be better off breaking the server names up into groups and setting a background job to work on each group. It takes about 5 seconds to set up and tear down a background job, and using them for trivial tasks like pinging a single computer can be counter-productive.

It's more work to code, but if you want to multi-thread that I think a runspace pool would produce results much faster than background jobs in this application.

Upvotes: 5

AlexPawlak
AlexPawlak

Reputation: 799

I am not sure whether there exists a build in module to manipulate CSV files.

You can either manipulate CSV file to give you the output or add NoteProperty to the existing variable.

Example 1:

(cat "C:\Users\test\Documents\serveurs.csv") -replace "Servername;IP", "Servername;IP;Available" -replace "64","64;" -replace "67","67;" | out-file "C:\Users\test\Documents\serveurs.csv"

Example 2:

$CSV | Add-Member -MemberType NoteProperty "Available" -Value "Yes"

This should sort out your needs, I guess.

EDIT:

Since the question was clarified, here is the proposed answer.

I am pretty sure there exists a simpler method to do this, but it works anyway

$CSV | Add-Member -MemberType NoteProperty "Available" -Value "" 
for ($i=0; $i -le $CSV.Length-1; $i++) {$CSV[$i].Available = Test-Connection $CSV[$i].Servername -quiet}

Upvotes: 3

Related Questions