check ping for multiple servers - powershell - powershell

how to check variables in each line of the text area and test them for ping
foreach ($textbox1 in $textbox1) {
if (test-Connection -ComputerName $textbox1 -Count 2 -Quiet)
{
$path = "$([Environment]::GetFolderPath("Desktop"))\ping.txt";
"$textbox1 is Pinging " | fl > $path; notepad $path;
}
else
{
$path = "$([Environment]::GetFolderPath("Desktop"))\notping.txt";
"$textbox1 not pinging" | fl > $path; notepad $path;
}
}
I want to check for each variable in text area individually and check them each whether it pings or not

Based on your comment, I will use an example of getting the content from a text file:
$Servers = gc "(path to txt file, 1 server per line)"
foreach($Server in $Servers){
if (Test-Connection -ComputerName $Server -Count 2 -Quiet) {
Write-Host "$Server is Pinging "
} else {
Write-Host "$Server not pinging"
}
}

Related

PowerShell Loop Ping Online Status

I'm trying to modify a Powershell to do the following work, but I got into some errors.
My goal is to monitor multiple servers online status from the the Powershell window. I would need to open a Powershell and run the ps1 script from the Powershell window then monitor the online status result.
1. Ping servers from a list from hostname.txt
2. If server pingable and online return hostname and ip in Green
3. If server timeout return hostname and ip in red
4. Loop back to the first server and ping again
Please help. Thank You !
$name=Get-content "c:\temp\hostname.txt"
foreach($name in $names) {
if(Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue) {
Write-Host "$name is up" -foregroundColor Green
$output+="$name is up,"+"'n"
}
else {
Write-Host "$name is up" -foregroundColor Red
$output+="$name is down,"+"'n"
}
}
Here's an old script I have called pinger that does something similar. It uses a hashtable, so it only reports changes in status, and sleeps a little at the end of the loop. It also beeps. If I output an object instead of text, there would be a delay until 2 objects were output.
# pinger.ps1
# example: pinger comp1
# pinger comp1,comp2,comp3
# $list = cat comps.txt; pinger $list
param ($hostnames)
$pingcmd = 'test-connection'
$sleeptime = 1
$sawup = #{}
$sawdown = #{}
foreach ($hostname in $hostnames) {
$sawup[$hostname] = $false
$sawdown[$hostname] = $false
}
while ($true) {
foreach ($hostname in $hostnames) {
if (& $pingcmd -count 1 $hostname -ea 0) {
if (! $sawup[$hostname]) {
echo "$([console]::beep(500,300))$hostname is up $(get-date)"
$sawup[$hostname] = $true
$sawdown[$hostname] = $false
}
} else {
if (! $sawdown[$hostname]) {
echo "$([console]::beep(500,300))$hostname is down $(get-date)"
$sawdown[$hostname] = $true
$sawup[$hostname] = $false
}
}
}
sleep $sleeptime
}
pinger microsoft.com,yahoo.com
microsoft.com is down 07/22/2021 09:55:15
yahoo.com is up 07/22/2021 09:55:15
If you want it to repeat in perpetuity, wrap the whole thing in a while($true){...} loop:
while($true){
$names = Get-content "c:\temp\hostname.txt"
foreach ($name in $names) {
if (Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue) {
Write-Host "$name is up" -foregroundColor Green
$output += "$name is up," + "'n"
}
else {
Write-Host "$name is up" -foregroundColor Red
$output += "$name is down," + "'n"
}
}
}
If you want to show the resolved IP address, make sure you save the output from Test-Connection to a variable:
if($ping = Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue){
Write-Host "$name [IP: $($ping.ProtocolAddress)] is up" -ForegroundColor Green
$output += "$name [IP: $($ping.ProtocolAddress)] is up `n"
}

PowerShell - How do you get the latest windows updates from a list of servers? Array/For Each problem

I think the issue is in the $computer and foreach sections. When I run this nothing returns. What am I missing please?
$computer = #('server1', 'server2')
ForEach ($COMPUTER in (Get-ADComputer -Filter ('Name -like "{0}"' -f $computer)))
{if(!(Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{write-host "cannot reach $computer" -f red}
else {
$key = "SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install"
$keytype = [Microsoft.Win32.RegistryHive]::LocalMachine
$RemoteBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($keytype,$Server)
$regKey = $RemoteBase.OpenSubKey($key)
$KeyValue = $regkey.GetValue("LastSuccessTime"”)
$System = (Get-Date -Format "yyyy-MM-dd hh:mm:ss")
if ($KeyValue -lt $System)
{
Write-Host " "
Write-Host $computer "Last time updates were installed was: " $KeyValue
}
}
}
Thanks for your help.
i think this should work. But at the moment i have no possibility to test it.
Some explanations:
name var ADComputer instead of COMPUTER
$COMPUTER and $coMpUTeR and $COMputer and $computer are all the same because of powershell's case-insensitivity
create var outside the loop, if you don't change them in it
if ($KeyValue -lt $System) makes no sense it will always be true, because the last successfull installation will always be in the past
Keep it simple, you can easily get the remote's registry value with the Invoke-Command, which allows you to "invoke" a script block on a remote host and returns its output. Also it is simpler to call the registry with the Get-ItemPropertyValue cmdlet.
# create array computer
$computer = #('server1', 'server2')
# store Registry key
$key = “HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install”
# iterate through computers
$computer.Foreach({
# Get Computer from AD
$ADComputer = Get-ADComputer $_
# Test if server is not reachable and report it
if(!(Test-Connection -Cn $ADComputer.DNSHostName -BufferSize 16 -Count 1 -ea 0 -quiet)){
Write-Host ("cannot reach {0} " -f $_) -ForegroundColor Red
}else{
# Get remote computers registry entry
$KeyValue = Invoke-Command { (Get-ItemProperty -Path $args[0] -Name "LastSuccessTime") } -ComputerName $ADComputer.DNSHostName -ArgumentList $key
Write-Host " "
# write LastSuccessTime to host
Write-Host ("{0}: Last time updates were installed was: {1}" -f $ADComputer.Name, $KeyValue)
}
})

Slow Processing Script in Powershell, Worklfow first steps

as i was wondering why my script takes so long i was seachring on google and also here in stackoverflow.
But all that i could find any close to helpful was this one here, Powershell Script Running Slowly
As I'm still pretty new to Powershell this is a little complicated to get through and take over to my script as i dont know how to handle those mentiond things anyway as i never heard of it before.
My Script is pretty easy and just gives me some Informations if there is something that returns an echo or not.
I wanted to "scan" our entire Network so I made an csv with out local Networks IP's and pass it to Powershell to "Ping" those.
But I realised that the "was not responing" part takes a long time to execute.
$list = Import-Csv -Path D:\ipcheck3.csv -UseCulture
$x=$list.IP
$ErrorActionPreference = "SilentlyContinue"
foreach ($y in $x)
{
try
{
if(Test-Connection $y -Count 1 -quiet)
{
write-host "$y responded"
$y | Export-Csv -Path D:\PingSucceded.csv -Append
}
else
{
Write-Host "$y was not responding"
$y | Export-Csv -Path D:\Pingfailed.csv -Append
}
}
catch
{
Write-Warning "Other Error occured"
}
}
There are not only Windows Clients out there so WMI is not an option and I don't know how to achvie this otherwise
EDIT:
After the Workflow input this is my "Try Version"
workflow Test-IPrange
{
Param
(
$IPs
)
$tocheck= $IPs.IP
foreach -parallel ($IP in $tocheck)
{
$pingsucceed = Test-Connection $IP -Count 1 -quiet
if($pingsucceed -eq "True")
{
$IP | Export-Csv -Path D:\testj.csv -Append
}
else
{
$IP | Export-Csv -Path D:\testn.csv -Append
}
}
}
Test-IPrange -IPs $(Import-Csv -Path D:\ipcheck3.csv -UseCulture)
My Output of Workflow Try
#TYPE System.String
PSComputerName,"PSShowComputerName","PSSourceJobInstanceId","Length"
localhost,"True","4e208e38-f7c2-492f-9d81-6583a103c3ac","12"
localhost,"True","4e208e38-f7c2-492f-9d81-6583a103c3ac","12"
With the Help of #Fourat
i edited my code to this form
Function Custom-Ping {
Param(
[string]$Address
)
$ping = ping $Address /w 1 /n 1
$result = ![string]::IsNullOrEmpty($ping -Like "*(0% Verlust)*")
return $result
}
$list = Import-Csv -Path D:\ipcheck3.csv -UseCulture
$x=$list.IP
$ErrorActionPreference = "SilentlyContinue"
foreach ($y in $x)
{
try
{
if(Custom-Ping $y)
{
Write-Host "$y responded"
$y | Export-Csv -Path D:\PingsuccededV3.csv -Append
}
else
{
Write-Host "$y was not responding"
$y | Export-Csv -Path D:\PingfailedV3.csv -Append
}
}
catch
{
Write-Warning "Textline from CMD Command or other Error"
}
}
which works properly good and is faster
I think that your process time is spoiled by the timeouts. If all your IPs are in the local network, try to reduce the timeout (because the default value is 5 seconds).
If you have Powershell 6 :
Test-Connection $y -Count 1 -quiet -TimeoutSeconds 1
If you don't, just use ping :
ping 58.47.45.1 /w 1 /n 1
You can also use a parallel for each loop, but it won't help much if you have multiple fails :
ForEach -Parallel ($x in $y)
{
...
}
UPDATE
In order to handle ping results, you can use a function like this (I used the keyword 'perte' because my computer is in French) :
Function Custom-Ping {
Param(
[string]$Address
)
$ping = ping $Address /w 1 /n 1
$result = ![string]::IsNullOrEmpty($ping -Like "*(perte 0%)*")
return $result
}
I've used Workflow to solve this issue my self. It's a few years ago I did it, so something better and newer is out there. But this works great for me...
I've ping over 2000 computers within a few Min...
workflow Test-ComputersConnection
{
Param
(
# Param1 help description
$Computernames#,
# Param2 help description
# [int]
# $Param2
)
foreach -parallel ($ComputerName in $Computernames)
{
$ConnectionTest = Test-Connection -ComputerName $ComputerName -ErrorAction SilentlyContinue -Count 1
if ($ConnectionTest.Address -eq $ComputerName) {
Write-Output $(Add-Member -MemberType NoteProperty -Name "Computername" -Value $ComputerName -InputObject $ConnectionTest -PassThru )
#Write-Verbose -Verbose -Message "[$($ComputerName)]: Replays on Ping."
}
Else {
#Write-Verbose -Verbose -Message "[$($ComputerName)]: Do not replays on Ping."
}
}
}
$OnlineNow0 = Test-ComputersConnection -Computernames $( Import-Csv -Path D:\ipcheck3.csv -UseCulture |
Select-Object -ExpandProperty name)
The code above is a quick edit of what I use... You will need to edit the $(Import ...) statement first, to make sure the PC name is being deliveret to the workflow.
I've just testet on my own computer and it gave me a reply...

Check if computer is online, if so, echo "$Computername is online" script [duplicate]

I have a large list of hostnames I need to ping to see if they are up or down. I'm not really that great at scripting but I managed to figure this much out:
$names = Get-content "hnames.txt"
foreach ($name in $names){
if (Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue){
Write-Host "$name is up" -ForegroundColor Green
}
else{
Write-Host "$name is down" -ForegroundColor Red
}
}
This gets me what I need but i now need to write out these results to a csv file and i have no idea how to do that.
Please Help!
You can use the following code instead (I simply altered the write-host calls to CSV formatting) and execute it with "PowerShell.exe script.ps > output.csv"
Note that you must execute it from the folder that contains hnames.txt, or simply change the "hnames.txt" to a full path.
$names = Get-content "hnames.txt"
foreach ($name in $names){
if (Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue){
Write-Host "$name,up"
}
else{
Write-Host "$name,down"
}
}
P.S. You can also use the Out-File Cmdlet to create the CSV file
I am a complete newbie to Powershell, so I took this on as a learning task, as I needed a quick and simple way to check a list of PC's for up/down status. These tweaks were needed to get it to output cleanly to the screen and to a txt file
$Output= #()
$names = Get-content "hnames.txt"
foreach ($name in $names){
if (Test-Connection -ComputerName $name -Count 1 -ErrorAction SilentlyContinue){
$Output+= "$name,up"
Write-Host "$Name,up"
}
else{
$Output+= "$name,down"
Write-Host "$Name,down"
}
}
$Output | Out-file "C:\support\result.csv"
$Output= #()
$names = Get-Content ".\input\Servers.txt"
foreach ($name in $names){
if (Test-Connection -Delay 15 -ComputerName $name -Count 1 -ErrorAction SilentlyContinue -quiet){
$Output+= "$name,up"
Write-Host "$Name,up" -ForegroundColor Green
}
else{
$Output+= "$name,down"
Write-Host "$Name,down" -ForegroundColor Red
}
}
$Output | Out-file ".\output\result.csv"
This is a tad cleaner, and includes the original foreground options but, BTW, the 'delay' switch seems to be ignored -PB
I would do it this way. Using a list of computers and -asjob works very well. The Responsetime property (confusingly the header is "Time(ms)") will be non-null if the host is up.
$names = Get-content hnames.txt
test-connection $names -asjob -count 1 | receive-job -wait -auto
Source Destination IPV4Address IPV6Address Bytes Time(ms)
------ ----------- ----------- ----------- ----- --------
COMP001 yahoo.com 74.6.231.21 32 39
COMP001 microsoft.com 40.113.200.201 32
Lately I do it this way. It requires threadjobs installed in powershell 5.1. Or just use get-port. I stick it in a mymod\mymod.psm1 module file somewhere in $env:psmodulepath. I can check a classroom in under 10 seconds.
function get-pport { # multi-threaded
param($list)
$list |
% { $_ | start-threadjob { get-port $input } -throttlelimit 20 } |
receive-job -wait -auto
}
function Get-Port {
Param (
[parameter(ValueFromPipeline)]
[string[]]$Hostname='yahoo.com'
)
begin {
$ports = 22,5988,3389,5985
$ping = New-Object System.Net.Networkinformation.ping
$Timeout = 200 # ms
}
process {
$hostname | foreach {
$openPorts = #()
foreach ($port in $ports) {
$client = New-Object System.Net.Sockets.TcpClient
$beginConnect = $client.BeginConnect($_,$port,$null,$null)
Start-Sleep -Milli $TimeOut
if($client.Connected) { $openPorts += $port }
$client.Close()
}
$result = $Ping.Send($_, $timeout)
if (! $result) { write-error "hostname $_ not found" }
$pingstatus = ($result.status -eq 'Success')
New-Object -typename PSObject -Property #{
HostName = $_
Port = $openPorts
Ping = $pingstatus
} | select hostname,port,ping
} # end foreach
} # end process
}
Example:
$avid = cat afile.txt
pport $avid
HostName Port Ping
-------- ---- ----
A006 {3389, 5985} True
A011 {3389, 5985} True
A015 {3389} True

Easily hide error given by PS and show message

im currently finishing my PS script to get the time from a list of servers and export them to a .txt file. Thing is that servers with connection problems gives just a PS error. I want that servers with connection issues get logged also and by just a message i.e "Server server name not reachable". Thanks a lot for your help!
cls
$server = Get-Content srvtime_list.txt
Foreach ($item in $server)
{
net time \\$item | find /I "Local time" >> srvtime_result.txt
}
I'd probably rewrite your code a bit:
Get-Content srvtime_list.txt |
ForEach-Object {
$server = $_
try {
$ErrorActionPreference = 'Stop'
(net time \\$_ 2>$null) -match 'time'
} catch { "Server $server not reachable" }
} |
Out-File -Encoding UTF8 srvtime_result.txt
There are other/better ways to get the time (as others suggested) but to answer your question:
You can suppress errors by redirecting the error stream to null.
Check the $LASTEXITCODE variable, any result other than 0 means the command did not completed successfully.
Get-Content srvtime_list.txt | Foreach-Object{
net time \\$_ 2>$null | find /I "Current time" >> srvtime_result.txt
if($LASTEXITCODE -eq 0)
{
$result >> srvtime_result.txt
}
else
{
"Server '$_' not reachable" >> srvtime_result.txt
}
}
I'd do something like this:
Get-Content srvtime_list.txt | %{
$a = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $_ -erroraction 'silentlycontinue'
if ($a) { "$_ $($a.ConvertToDateTime($a.LocalDateTime))" } else { "Server $_ not reachable" }
} | Set-Content srvtime_result.txt
Use the Test-Connection cmdlet to verify that the remote system is reachable.
cls
$server = Get-Content srvtime_list.txt
Foreach ($item in $server)
{
if (test-connection $item) {
net time \\$item | find /I "Local time" >> srvtime_result.txt
} else {
"$item not reachable" | out-file errors.txt -append
}
}
But you can do this in pure Powershell, without resorting to net time - use WMI. This is untested as I don't have Windows handy at the moment, but it's at least 90% there.
cls
$server = Get-Content srvtime_list.txt
$ServerTimes = #();
Foreach ($item in $server)
{
if (test-connection $item) {
$ServerTimes += Get-WMIObject -computername $name win32_operatingsystem|select systemname,localdatetime
} else {
"$item not reachable" | out-file errors.txt -append
}
}
$ServerTimes |Out-File srvtime_result.txt