Last active
May 4, 2017 10:06
-
-
Save bevinduplessis/b22f733cd3977dcfb6dff4a37ed4397c to your computer and use it in GitHub Desktop.
Powershell Ping Class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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