I have executed my script and I am getting the output results
Suppose I am checking ping status for 5 servers, then for the very first time I am running the script then in mail body I am getting the output of 5 servers only, but second time I am running the same script it is giving output in mail body but it is also showing the first results as well.
If I run the script again it will display same results three times and so on, like below:
Please anyone suggest how can I remove this repetition over email body.
OUTPUT WHICH I AM GETTING:
1.2.3.4.5 could not find host
X is success
Y is failed
Z is success
H is failed
1.2.3.4.5 could not find host
X is failed
Y is failed
Y is failed
Z is failed
H is failed
OUTPUT WHICH I AM EXPECTING TO DISPLAY DURING THAT TIME:
1.2.3.4.5 could not find host
X is success
Y is failed
Z is success
H is failed
Script:
cls
$ip = Get-Content -Path 'D:\ping text.txt'
foreach ( $ip1 in $ip ) {
$ip2 = ping $ip1
if ( $ip2 -imatch "(100% loss)")
{
Write-Host "$ip1 is failed" -ForegroundColor Red
$output="$ip1 is failed"
}
elseif ($ip2 -imatch "Ping request could not find host")
{
Write-Host "$ip1 could not find host" -ForegroundColor Red
$output = "$ip1 could not find host"
}
else
{
Write-Host "$ip1 is success" -ForegroundColor Green
$output="$ip1 is success"
}
$output | Out-File "D:\result.html" -append
}
$body = Clear-Content [System.IO.File]::ReadAllText("D:\result.html")
Send-MailMessage -From 'X' -To 'Y' -Subject 'Sending the Attachment' -Body $body -Attachments D:\result.html -Priority High -SmtpServer 'webmail.wipro.com' -Port 587
CodePudding user response:
To continue from my comments, I woud not try to create a file and send that as attachment, but rather add the results in the email body.
This prevents your error that earlier output in the attachment is kept because you append messages to a file without removing it first.
Also, Out-File
does not create a HTML file unless you add the HTML tags, newlines etc, to the messages yourself.
Also, for the receiver of the email, it is nicer because they do not have to click to open an attached file.
Try
# read the list of IP addresses making sure duplicates are removed
$ipAddresses = Get-Content -Path 'D:\ping text.txt' | Select-Object -Unique
# loop through the IP addresses and test them. Collect the results in variable $output
$output = foreach ( $ip in $ipAddresses ) {
try {
Test-Connection -ComputerName $ip -Count 1 -ErrorAction Stop
Write-Host "$ip is OK" -ForegroundColor Green
# output an object with the IP and the Success message
[PsCustomObject]@{IP = $ip; Message = 'Success'}
}
catch {
Write-Host "$ip failed" -ForegroundColor Red
# output an object with the IP and the failure message
[PsCustomObject]@{IP = $ip; Message = $_.Exception.Message}
}
}
# show the results as table in the email message
# for HTML mail, either build a nice CSS style and use something like
# $body = $output | ConvertTo-Html -Title ('Connection Test {0:yyyy-MM-dd HH:mm:ss}' -f (Get-Date))
# as demo here, format the result as table and wrap that in '<pre>..</pre>' tags
# so it wil show up with a monospaced font, looking the same as in the console.
$body = '<pre>{0}</pre>' -f ($output | Format-Table -AutoSize -Wrap | Out-String)
# best use Splatting on cmdlets that take a lot of parameters:
$mailParams = @{
From = '[email protected]'
To = '[email protected]'
Subject = 'Connection Test {0:yyyy-MM-dd HH:mm:ss}' -f (Get-Date)
Body = $body
BodyAsHtml = $true
Priority = 'High'
SmtpServer = 'webmail.wipro.com'
Port = 587
# more parameters go here
}
# send the email
Send-MailMessage @mailParams
As requested some explanation to the above:
The foreach
loop iterates over the (unique) set of IP addresses and by prefixing that loop with $output =
, everything that outputs something inside the loop gets captures (collected) in that variable.
Write-Host
only sends output to console screen, so there is nothing that gets collected from that.
What you DO want to output is an object with two properties: 'IP' and 'Message'.
To create such an object real easy, use PsCustomObject
You output this when the ping (Test-Connection by default uses ping in the background) is successful, but also when an error occurs.
You handle both success and error in a try{..} catch{..}
construct and for that to catch all exceptions, you need to add -ErrorAction Stop
to the cmdlet that can throw an exception.
If all goes well, only the code inside try{..}
gets executed. Only if an error occurs, the code inside the catch{..}
gets executed.
As I have commented earlier, there can be a lot of different error messages, all happily returned to you inside the catch{..}
in the $_.Exception.Message
property, so there is no need to try and spell these out yourself. ($_
is an Automatic variable that inside a catch
represents the exception object itself)
Why this doesn't repeat output from earlier runs is because we are not appending to a file, but instead collect everything in memory in a (re) new $output
variable.
Hope that explains.
Please read the links I gave for better understanding.
CodePudding user response:
Delete the file you are appending to before appending
Please correct the script if it gives errors. I do not normally script powershell
cls
$ip = Get-Content -Path 'D:\ping text.txt'
$fileName = "D:\result.html"
if (Test-Path $FileName = True) {
Remove-Item $FileName
}
foreach ( $ip1 in $ip ) {
$ip2 = ping $ip1
if ( $ip2 -imatch "(100% loss)")
{
Write-Host "$ip1 is failed" -ForegroundColor Red
$output="$ip1 is failed"
}
elseif ($ip2 -imatch "Ping request could not find host")
{
Write-Host "$ip1 could not find host" -ForegroundColor Red
$output = "$ip1 could not find host"
}
else
{
Write-Host "$ip1 is success" -ForegroundColor Green
$output="$ip1 is success"
}
$output | Out-File $fileName -append
}
$body = Clear-Content [System.IO.File]::ReadAllText($fileName)
Send-MailMessage -From 'X' -To 'Y' -Subject 'Sending the Attachment' -Body $body -Attachments $fileName -Priority High -SmtpServer 'webmail.wipro.com' -Port 587