Kenny
Kenny

Reputation: 151

Import CSV with headers, scan for log on remote servers, add data to array, export array to CSV

I need to go back to the drawing board with a template I've been using for about a year that reads values from a .csv with headers, opens a hashtable array, updates various properties on the servers as the scans are run (ping, logs, services, etc) and finally exports to .csv or gridview.

The hashtable-based array template was working fine for various functions over the past while, but I've found it doesn't work when attempting to do mass GCI scans against multiple servers. So tonight, I tried to re-write using regular @() arrays. However, there are two issues:

Here's the code:

$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
$ShortDate = (Get-Date).ToString('MM/dd/yyyy')
$InputCSV = @(Import-csv $Dir\Masters.csv)

function PingEM {
    Param($_)
    $Error.Clear()
    try {
        $Ping = New-Object System.Net.NetworkInformation.Ping
        $PingReturn = $Ping.Send($_, 1000) | select Status -ExpandProperty Status
    } catch {}

    if (($Error) -or ($PingReturn -ne "Success")) {
        Write-Host "$_ is offline. Remaining checks will be skipped" -ForegroundColor Red
        $Ping = "Offline"
        $TaskSeq = "N/A"
        $Completed = "N/A"
    } else {
        Write-Host "Online" -ForegroundColor Green
        $Ping = "Online"
    }
}

$OutArray = @()

foreach ($Item in $InputCSV) {
    $outarray += New-Object PSObject -Property @{
        Server = $Item.Server
        Platform = $Item.Platform        
    }

    PingEM $($Item.Server)

    if ($Ping -eq "Online") {
        Write-Host "Checking $($Item.Server) now"

        if (GCI \\$($Item.Server)\c$\log\Results_*.html -EA 0 | Where { $_.LastWriteTime -ge "$ShortDate" }) {
            Write-Host "Recent log found!"
        } else {
            Write-Host "Recent log NOT found!"
        }
    }
} # PING

$OutArray

Upvotes: 0

Views: 111

Answers (2)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200463

There are several issues with your code:

  • $_ is an automatic variable. Don't use it as a Param().
  • You create and initialize $Ping in the local scope of PingEM(). The $Ping in the if condition is a different variable (in a different scope), hence it's empty.
  • You're using the variable $Ping inside PingEM() for different things (the Ping object as well as the status string). Don't re-use variables.
  • Have your function actually return the status (or a status object). PowerShell functions return all non-captured output on the Success output stream, so simply echoing "Online" or "Offline" would suffice.
  • Using cmdlets like Test-Connection is usually more PoSh than using .Net classes like System.Net.NetworkInformation.Ping. There are situations where .Net classes are preferrable for performance reasons, but most of the time cmdlets are simpler and more straightforward to use.

Change your function to this:

function PingEM {
    Param($server)

    if (Test-Connection $server -Count 1 -TimeToLive 1 -Quiet) {
        Write-Host "Online" -ForegroundColor Green
        'Online'
    } else {
        Write-Host "$_ is offline. Remaining checks will be skipped" -ForegroundColor Red
        'Offline'
    }
}

so you can use it like this:

if ((PingEM $Item.Server) -eq 'Online') {
  ...
}

Note that you need to put the function call in parentheses, otherwise PowerShell would interpret -eq as a parameter to the function instead of the equality comparison operator. And you only need a subexpression around $Item.Server if you use it inside a string.

Upvotes: 0

jj27
jj27

Reputation: 178

The code below should work. You had a typo with $.LastWriteTime where you needed to use $_.LastWriteTime. You were also trying to define variables of $Server and $Platform, rather than specifying those as properties in the hash table. Lastly, revised your GCI command to reference $($Item.Server) rather than an undefined variable of $Server.

Code:

$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
$ShortDate = (Get-Date).ToString('MM/dd/yyyy')
$InputCSV = @(Import-csv $Dir\Servers.csv)

$OutArray = @()

ForEach ($Item in $InputCSV) 
{
    if (GCI \\$($Item.Server)\c$\*.log -EA 0 | Where { $_.LastWriteTime -ge "$ShortDate" })
    {
        $Completed = "Yes"
    }else{
        $Completed = "No"
    }

    $outarray += New-Object PsObject -property @{
    Server = $Item.Server
    Platform = $Item.Platform
    Completed = $Completed
    }

} 
$OutArray

Upvotes: 1

Related Questions