Skip to content

Instantly share code, notes, and snippets.

@bevinduplessis

bevinduplessis/Ping.ps1

Last active May 4, 2017
Embed
What would you like to do?
Powershell Ping Class
class Ping
{
# Property
[array] $Results
[array] $Online
[array] $Offline
$ExecutionTime
$TotalComputers
$OnlineCount
$OnlinePercent
$OfflineCount
$OfflinePercent
# Constructor
Ping ([array] $Computers)
{
function Invoke-MultiThreadedCommand
{
[CmdletBinding()]
param(
[parameter(Mandatory = $True,ValueFromPipeline = $True,Position = 0)]
$ProcessArray,
[parameter(Mandatory = $True)]
[ScriptBlock]$Scriptblock,
[parameter()]
$ThrottleLimit = 32,
[parameter()]
[switch]
$ShowProgress
)
Begin
{
# Create runspacepool, add code and parameters and invoke Powershell
[void][runspacefactory]::CreateRunspacePool()
$SessionState = [Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
$script:RunspacePool = [runspacefactory]::CreateRunspacePool(1,$ThrottleLimit,$SessionState,$host)
$RunspacePool.Open()
# Function to start a runspace job
function Start-RSJob
{
param(
[parameter(Mandatory = $True,Position = 0)]
[ScriptBlock]$Code,
[parameter()]
$Arguments
)
if ($RunspacePool.GetAvailableRunspaces() -eq 0)
{
do
{
}
Until ($RunspacePool.GetAvailableRunspaces() -ge 1)
}
$PowerShell = [powershell]::Create()
$PowerShell.runspacepool = $RunspacePool
[void]$PowerShell.AddScript($Code)
foreach ($Argument in $Arguments)
{
[void]$PowerShell.AddArgument($Argument)
}
$job = $PowerShell.BeginInvoke()
# Add the job and PS instance to the arraylist
$temp = '' | Select-Object -Property PowerShell, Job
$temp.PowerShell = $PowerShell
$temp.Job = $job
[void]$Runspaces.Add($temp)
}
# Start a 'timer'
$Start = Get-Date
# Define an arraylist to add the runspaces to
$script:Runspaces = New-Object -TypeName System.Collections.ArrayList
$i = 0
}
Process
{
# Start an RS job for each computer
$ProcessArray | ForEach-Object -Process {
if ($PSCmdlet.MyInvocation.BoundParameters['Verbose'].IsPresent)
{
$host.UI.WriteVerboseLine("Starting RS job for $_")
}
Start-RSJob -Code $Scriptblock -Arguments $_
$i ++
if ($ShowProgress)
{
Write-Progress -Activity 'Invoking Jobs' -CurrentOperation $_
}
}
}
End
{
# Wait for each script to complete
if ($PSCmdlet.MyInvocation.BoundParameters['Verbose'].IsPresent)
{
$host.UI.WriteVerboseLine('Waiting for RS jobs to finish')
}
$x = 0
foreach ($item in $Runspaces)
{
$x ++
if ($ShowProgress)
{
Write-Progress -Activity 'Retrieving Job Output' -PercentComplete ($x / $i * 100) -Status "$([math]::Round(($x / $i * 100),0)) %"
}
do
{
}
until ($item.Job.IsCompleted -eq 'True')
}
# Grab the output from each script, and dispose the runspaces
if ($PSCmdlet.MyInvocation.BoundParameters['Verbose'].IsPresent)
{
$host.UI.WriteVerboseLine('Retrieving results and disposing runspaces')
}
$return = $Runspaces | ForEach-Object -Process {
$_.powershell.EndInvoke($_.Job)
$_.PowerShell.Dispose()
}
$Runspaces.clear()
[void]$RunspacePool.Close()
[void]$RunspacePool.Dispose
# Stop the 'timer'
$End = Get-Date
$TimeTaken = [math]::Round(($End - $Start).TotalSeconds,2)
if ($PSCmdlet.MyInvocation.BoundParameters['Verbose'].IsPresent)
{
$host.UI.WriteVerboseLine("Command completed in $TimeTaken seconds")
}
# Return the results
$return
}
}
# Define the "Test-Connection" code
$Code = {
param($ComputerName)
$RetryCount = 5
1..$RetryCount | ForEach-Object -Process {
$Params = @{
ComputerName = $ComputerName
BufferSize = 1
Count = 1
ErrorAction = 'SilentlyContinue'
}
$t = Test-Connection @Params
if($t -eq $True)
{
Break
}
}
if($t)
{
$t
}
}
$Start = Get-Date
$Result = $Computers | Invoke-MultiThreadedCommand -Scriptblock $Code -ShowProgress -ThrottleLimit 128
$End = Get-Date
$On = $Result.ForEach{
$_.Address
}
$Off = $Computers.Where{
$_ -notin $On
}
$this.Results = $Result
$this.Online = $On
$this.Offline = $Off
$this.ExecutionTime = "$([math]::Round(($End - $Start).TotalSeconds,2)) seconds"
$this.OfflineCount = $Off.Count
$this.OnlineCount = $On.Count
$this.TotalComputers = $Computers.Count
$this.OnlinePercent = "$([math]::Round(($($On.Count) / $($Computers.Count) * 100))) %"
$this.OfflinePercent = "$([math]::Round(($($Off.Count) / $($Computers.Count) * 100))) %"
}
}
[ping]$Results = (Get-ADComputer -Filter {
OperatingSystem -like '*Windows Server*'
}).DNSHostName
Write-Host "TotalComputers: $($Results.TotalComputers)"
Write-Host "OnlineCount: $($Results.OnlineCount)"
Write-Host "OnlinePercent: $($Results.OnlinePercent)"
Write-Host "OfflineCount: $($Results.OfflineCount)"
Write-Host "OfflinePercent: $($Results.OfflinePercent)"
Write-Host "ExecutionTime: $($Results.ExecutionTime)"
Write-Host ' '
Foreach ($Result in $($Results.Offline))
{
Write-Host "Host $Result is offline"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment