One Email to Rule them All - email

I have this script that takes a CSV and pings servers and tells me their status and then sends me an email on ones that are unreachable. The Below script works great, but the only thing I would like to change is instead of receiving multiple e-mails per unreachable server I get one email containing all of the servers that are unreachable after it has finished pinging.
I know that part of the problem is that I have the email line inside the IF, Else. So I was thinking about creating a variable and doing a new line, but I need help to see what that looks like.
Any help or advice would be appreciated. I've tried looking on Microsoft's script page and googling as well.
$hostnamestxt = "C:\Scripts\printers.csv"
$servers = Import-Csv "$hostnamestxt"
$date = get-date
foreach($server in $servers) {
$serverName = $server.Name
$serverAddress = $server.IP
if (test-Connection -ComputerName $serverAddress -Count 2 -Quiet)
{
write-host "$serverName is ONLINE" -foregroundcolor black -backgroundcolor green
}
else
{
write-host "$serverName, $serverAddress is OFFLINE/UNREACHABLE" -foregroundcolor black -backgroundcolor red
Send-MailMessage -Body "$serverName, $serverAddress is OFFLINE/UNREACHABLE at $date" -From "emailaddress" -Subject "$serverName, $serverAddress is OFFLINE/UNREACHABLE at $date" -To "emailaddress" -SmtpServer "emailaddress"
}
}

You could create an empty array and then add the server name for devices that are offline, then you would send the email. Something like this would probably do what you are looking for:
$servers = Import-Csv -Path "C:\Scripts\printers.csv"
$date = get-date
$Array = #()
foreach ($server in $servers) {
$serverName = $server.Name
$serverAddress = $server.IP
if (test-Connection -ComputerName $serverAddress -Count 2 -Quiet)
{
write-host "$serverName is ONLINE" -foregroundcolor black -backgroundcolor green
}
else
{
write-host "$serverName, $serverAddress is OFFLINE/UNREACHABLE" -foregroundcolor black -backgroundcolor red
$Array += $serverName
}
}
Send-MailMessage -Body "The Following Devices are Offline $Date: $Array" -From "emailaddress" -Subject "Servers Offline $date" -To "emailaddress" -SmtpServer "emailaddress"

Related

loop through servers and send single email with results instead of an email for each result

foreach ($server in '192.168.1.5', '192.168.1.6', '192.168.1.7') {
$availablespace = [Math]::Truncate((Get-WmiObject -Class Win32_LogicalDisk -ComputerName $server -Credential $arpcred | Where-Object { $_.DeviceID -eq 'C:' }).FreeSpace / 1GB)
Write-Host $server has $availablespace GB of available space
if ($availablespace -lt 10) {
Write-Host $server only has $availablespace GB of available space
Write-Host sending email
Send-MailMessage -From $from -To $to -Subject $subj -Body "$server only has $availablespace GB of available space" -SmtpServer $smtp -Credential $smtpcred -UseSsl -Port 587
}
}
This will loop through a list of servers and send an email for each server that has less than 10GB of free space available on C:.
How can I change it so it will send a single email containing a list of all the servers with less than 10GB of free disk space?
You can use dynamic array for the store value. Please find below code
$serverlist= $null
$serverlist= [System.Collections.ArrayList]#()
foreach ($server in '192.168.1.5', '192.168.1.6', '192.168.1.7') {
$availablespace = [Math]::Truncate((Get-WmiObject -Class Win32_LogicalDisk -ComputerName $server -Credential $arpcred | Where-Object { $_.DeviceID -eq 'C:' }).FreeSpace / 1GB)
Write-Host $server has $availablespace GB of available space
if ($availablespace -lt 10) {
$serverlist += $server
}
}
write-host $serverlist
You get all server list inside the $serverlist

Powershell get process script not working correctly

I want this script to show me WinWord processes which are running currently and to send an email alert out. Currently the 1st script works if there are WinWord processes running and lists them in an email BUT if they are no WinWord processes running the script fails advising parameter is empty or null, cannot find process.
The second script works if there are no processes and doesn’t throw the null or empty parameter if there are no WinWord processes running but only shows true or false by email. Not the list of processes running. Also would like to add some write host in the script for the email output to say. Below are the number of WinWord’s Processes running.
I am a newbie to PowerShell. I am learning as I go. I also used -erroraction silentlycontinue for the first script but when outputting to email it still fails with empty or null parameter.
Below are the scripts.
Doesn't work if process is not running, cannot accept argument which is null or empty. If process is running works perfect.
$winwords = (get-process -ComputerName Dummyserver -Name Winword |where-object { $_.Count -gt 0})| Out-String
Send-MailMessage -To "Dummyemail.co.uk" -From " Dummyemail.co.uk" -Subject "WinWord Check" -SmtpServer " Dummy.priv" -Body $winwords
Works if argument is null or empty but an email alert is out which says false or true BUT doesn't display the amount of processes running like the first script.
$processname = "Winword"
$instanceisrunning = (get-process -ComputerName Dummyserver| where-object { $_.Name -eq $processname }).count -gt 0 | Out-String
Send-MailMessage -To "Dummyemail co.uk" -From "Dummyemail.co.uk" -Subject "WinWord Check" -SmtpServer " Dummyemail.priv" -Body $isrunning
You have the right idea using where-object to limit the processes to just the name you want. The logic you are using for count greater than zero will return a boolean ($true or $false), which is why you are seeing that output.
If you want to always send a message when this is run, you can do this:
$instances = (get-process -ComputerName Dummyserver | where-object { $_.Name -eq $processname })
if($instances.count -gt 0)
{
$message = $instances | Out-String
}
else
{
$message = "No instances running"
}
Send-MailMessage -To "Dummyemail co.uk" -From "Dummyemail.co.uk" -Subject "WinWord Check" -SmtpServer " Dummyemail.priv" -Body $message
If you only want a message sent when instances are running:
$instances = (get-process -ComputerName Dummyserver | where-object { $_.Name -eq $processname })
if($instances.count -gt 0)
{
Send-MailMessage -To "Dummyemail co.uk" -From "Dummyemail.co.uk" -Subject "WinWord Check" -SmtpServer " Dummyemail.priv" -Body ($instances | Out-String)
}
Edit: Adding code to work of multiple computers with one email
$computers = #("dummyserver","otherserver","nextserver")
$processName = "WinWord"
$message = "$processName is running on the following:"
foreach ($computer in $computers)
{
$message += "Hostname: $computer"
$instances = (Get-Process -ComputerName $computers | Where-Object { $_.Name -eq $processName })
if($instances.count -gt 0)
{
$message += ($instances | Out-String)
}
else
{
$message += "No instances running"
}
}
Send-MailMessage -To "Dummyemail co.uk" -From "Dummyemail.co.uk" -Subject "WinWord Check" -SmtpServer " Dummyemail.priv" -Body $message
you can use ErrorAction as silentlyContinue which will make your script run even if there is an error "NO Winword instances".
$winwords = (get-process -ComputerName Dummyserver -Name Winword -ErrorAction
SilentlyContinue |where-object { $_.Count -gt 0})| Out-String
if($winwords -eq ""){
$winwords = "No Instances"
}
Send-MailMessage -To "Dummyemail.co.uk" -From " Dummyemail.co.uk" -Subject "WinWord
Check" -SmtpServer " Dummy.priv" -Body $winwords

How to remove computer in AD and email the computers that were removed to yourself

I am trying to remove a list of machines from AD that are in a txt file. I have no issue getting them removed. However once they are removed, I want PowerShell to email my group saying these machines were removed from AD. Can anyone provide some help?
I have tried If, try, and statements but cant seem to get it working.
Get-Content 'c:\temp\Remove AD Computers.txt' | % { Get-ADComputer -Filter { Name -eq $_ } } | Remove-ADObject -Recursive -Whatif
$Computerlist = Get-Content 'c:\temp\Remove AD Computers.txt'
ForEach($Computer in $Computerlist)
{
try{
Get-ADComputer $Computer -ErrorAction Stop
$output = "$Computer still exsists in AD."
}
catch{
$output = "$Computer has been removed from AD."
}
}
Write-Host $output
Send-MailMessage -From 'ADComputersRemoved#redgold.com' -To 'support#redgold.com' -Subject 'AD Computers removed' -Body "$output" -SmtpServer smtp.domain.com
I need this to remove the computer and then email me the results of the removal. Hope this is enough information. Any help would be fantastic.
If you modify your foreach loop like the following, you will have all of your computers in the list. Each loop iteration will add an indexed element to the $output array with a value of one of your two strings.
$output = ForEach($Computer in $Computerlist)
{
try{
Get-ADComputer $Computer -ErrorAction Stop
"$Computer still exsists in AD."
}
catch{
"$Computer has been removed from AD."
}
}
Since $output will be an array of strings, you will need to make that a string when you pass it into the -body parameter of Send-MailMessage. I used the -join operator with CRLF characters. You can use whatever you like. $output | out-string will accomplish something similar.
Send-MailMessage -From 'ADComputersRemoved#redgold.com' -To 'support#redgold.com' -Subject 'AD Computers removed' -Body ($output -join "`r`n") -SmtpServer smtp.redgold.com

App_Pool_Alert Powershell Script

I have written a power shell script which is used to monitor the status of IIS app pools. With current method whenever any pool goes down it throws me an alert that pool is stopped and after that it starts the pool again send email stating that pool is up. Since i have around 50 servers so number of mails are coming in bulk which causes spam sometimes. Could some one help me here so that script will scan the pool directory and place the result in a text/html file and send me the list that these pools are down in mail. Please find script below:-
###################################Declear Servers in text file##############################################
$Servers = Get-Content C:\Users\Desktop\server.txt
################ Scans each server and import IIS web-administration module##################################
$Servers | ForEach-Object {
Invoke-Command -ComputerName $_ -ScriptBlock {
Import-Module WebAdministration
cd IIS:/AppPools
$CompName = (Get-WmiObject -Class Win32_ComputerSystem).Name
$ApplicationPools = dir
foreach ($item in $ApplicationPools)
{
$ApplicationPoolName = $item.Name
$ApplicationPoolStatus = Get-WebAppPoolState $ApplicationPoolName
If($ApplicationPoolStatus.value -eq "Stopped")
{
send-mailmessage -to "vvv#gmail.com" -from "xxx#gmail.com" -subject "Application Pool:- $ApplicationPoolName is Down on $CompName " -Body "$ApplicationPoolName is down. Please check IIS/Event logs for RCA." -SmtpServer ###########
Start-WebAppPool -Name $ApplicationPoolName
send-mailmessage -to "vvv#gmail.com" -from "xxx#gmail.com" -subject "Application Pool:- $ApplicationPoolName is Up on $CompName " -Body "$ApplicationPoolName is Up and running fine." -SmtpServer #############
}
}
}}
##################################### End of Script ##########################################################
This is how I would rewrite the script:
###################################Declear Servers in text file##############################################
$Servers = Get-Content C:\server.txt
################ Scans each server and import IIS web-administration module##################################
$SMPTServer = "mail.server.com"
$result = "The following application pools were restarted:`n`n" # default output
$Servers | ForEach-Object {
$result += Invoke-Command -ComputerName $_ -ScriptBlock { # add output of scriptblock to $result
Import-Module WebAdministration
cd IIS:/AppPools
$CompName = (Get-WmiObject -Class Win32_ComputerSystem).Name
$ApplicationPools = dir
foreach ($item in $ApplicationPools)
{
$ApplicationPoolName = $item.Name
$ApplicationPoolStatus = Get-WebAppPoolState $ApplicationPoolName
If($ApplicationPoolStatus.value -eq "Stopped")
{
Write-Output "Server $CompName - Application pool $ApplicationPoolName is Down - Restarting`n" # any action is added to otput
Start-WebAppPool -Name $ApplicationPoolName
}
}
}
}
if ($result -ne "The following application pools were restarted:`n`n") { # If any action was taken send mail with $result
send-mailmessage -to "vvv#gmail.com" -from "xxx#gmail.com" -subject "Application Pool Maitenance" -Body $result -SmtpServer $SMPTServer
}
##################################### End of Script ##########################################################
First define a $result variable, in this case just a string.
Withing your scriptblock, you can write anything to piped output using Write-Output. This output is returned from Ivoke-Command and added to the $result variable.
At the end of your script check if $result variable has changed and send it as a body of an email if required.

Get PrimaryStatus of DCIM_PhysicalDiskView and Put it in a variable in Powershell

I am trying to use the primaryStatus from the DCIM_PhysicalDiskView and compare it to 3 (degraded hard disk). If there is a match, an email will be sent to notify the admin. Here is the code:
$computerNames = Get-Content -Path C:\scripts\nameTest.txt
foreach ($computer in $computerNames) {
write-host "$computer"
$value = "3"
$smtpserver = "mailserver.xxxx.com" # your mail server here
$smtpFrom = "xx#xxxx.com" # your from address, mail server will most likely allow any
$smtpTo = "xx#xxxx.com" #your email address here. can also be an array and will send to all
$MessageSubject = "Testing Failed Disk in $computer" #whatever you want the subject to be.
gwmi -Namespace root\dcim\sysman -computername $computer -Class DCIM_PhysicalDiskView | ForEach {$name = $_.Name; $primaryStatus = $_.PimaryStatus}
if( $primaryStatus -contains $value )
{
Send-MailMessage -SmtpServer $smtpserver -from $smtpFrom -to $smtpto -subject $messageSubject
Write-Host "error message sent"
}
}
My problem is that the command is not piping to the foreach. The $name and $primaryStatus are staying null, therefore not going through the if statement.
Any help on this will be greatly appreciated. Thanks!
The below is your code with the braces changed for the foreach loop. Note that you will still need to have the closing brace from your opening foreach-object.
gwmi -Namespace root\dcim\sysman -computername $computer -Class DCIM_PhysicalDiskView | ForEach-Object {
$name = $_.Name
$primaryStatus = $_.PrimaryStatus
if( $primaryStatus -eq $value )
{
Send-MailMessage -SmtpServer $smtpserver -from $smtpFrom -to $smtpto -subject $messageSubject
Write-Host "error message sent"
}
}
Fixed the typo for $_.PrimaryStatus as well. Is $primaryStatus an array? -Contains only works with arrays. I think you wanted -eq? I dont have access to that namespace so i cannot test my theory. Also, I think that you could change this a little with a Where-Object.
gwmi -Namespace root\dcim\sysman -computername $computer -Class DCIM_PhysicalDiskView |
Where-Object { $primaryStatus -eq $value } | ForEach-Object{
Send-MailMessage -SmtpServer $smtpserver -from $smtpFrom -to $smtpto -subject $messageSubject
Write-Host "error message sent"
}
disclaimer: I do not have that namespace so I cannot test this but the logic looks sounds so it should work.