Import CSV with headers, scan for log on remote se

2019-09-14 06:55发布

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:

  • The headers on the input CSV are "server" and "platform", but they aren't reflected in the output. Instead the column header for the first entry is shown.
  • The if (GCI ...) code isn't working, and I'm not sure why.

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

2条回答
beautiful°
2楼-- · 2019-09-14 07:19

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
查看更多
Lonely孤独者°
3楼-- · 2019-09-14 07:29

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.

查看更多
登录 后发表回答