I can get it to work against one server but now I need it to work against all servers in one OU.
$servers = Get-ADComputer -SearchBase ‘OU=Servers,DC=COMPANY,DC=COM’ -Filter ‘SamAccountName -like “ntprocps*”’ | Select-Object -Expand Name
Foreach ($servers in $servers) {
$wmiobjs = Get-WmiObject -Class win32_operatingsystem -Property CSName,LastBootupTime -ComputerName $Servers
$time = $wmi.ConvertToDateTime($wmi.lastbootuptime)
[TimeSpan] $uptime = New-TimeSpan $time $(get-date)
If ($uptime.Hours -gt 1)
{Send-MailMessage -From monitor@company.com -Subject “Server Uptime” -To kelly.farrell@company.com -Body "server didn’t reboot - $uptime " -SmtpServer exchange.internal.company.com}
THIS IS THE ONE THAT WORKS
Get-CimInstance -ComputerName server -ClassName win32_operatingsystem -Property * | select csname, lastbootuptime
$wmi = Get-WmiObject -Class Win32_OperatingSystem -Computer server
$time = $wmi.ConvertToDateTime($wmi.lastbootuptime)
[TimeSpan] $uptime = New-TimeSpan $time $(get-date)
If ($uptime.days -gt 1)
{Send-MailMessage -From monitor@company.com -Subject “Server Uptime” -To kelly.farrell@company.com -Body "server didn’t reboot - $uptime " -SmtpServer exchange.internal.company.com}
Hi Kelly,
First thing I notice when looking at your script, is your foreach loop.
You do foreach $servers (plurral):
foreach ($servers in $servers) { ... code here ... }
Where I expect you would want to do foreach $server (singular):
foreach ($server in $servers) { ... code here ... }
Further to that, you miss a closing curly brace in your foreach loop (might just be a copy/paste error), and you store your WMI object in $wmiobjs, but refor to $wmi when trying to read the data afterwards
This slightly modified version of your own script might do what you are after (beware: untested)
$servers = Get-ADComputer -SearchBase 'OU=Servers,DC=COMPANY,DC=COM' -Filter 'SamAccountName -like "ntprocps*"' | Select-Object -ExpandProperty Name
foreach ($server in $servers)
{
$wmi = Get-WmiObject -Class win32_operatingsystem -Property CSName,LastBootupTime -ComputerName $server
$time = $wmi.ConvertToDateTime($wmi.lastbootuptime)
[TimeSpan] $uptime = New-TimeSpan $time $(get-date)
if ($uptime.days -gt 1)
{
Send-MailMessage -From monitor@company.com -Subject "Server Uptime" -To kelly.farrell@company.com -Body "server didn't reboot – $uptime " -SmtpServer exchange.internal.company.com
}
}
thanks that worked - appreciate your help
If you wanted to get a SINGLE email with all of the servers that met your criteria, you could reformat it a bit like below. Also, if you are connecting to servers, especially that could be in the middle of a reboot cycle, you need to test the connection and do error handling on WMI. Take a look at this example (not tested):
$servers = Get-ADComputer -SearchBase 'OU=Servers,DC=COMPANY,DC=COM' -Filter 'SamAccountName -like "ntprocps*"' | Select-Object -Expand Name
$results = foreach ($server in $servers) {
if (Test-Connection -ComputerName $server -Count 2 -Quiet) {
try {
$os = Get-WmiObject -Class win32_operatingsystem -Property LastBootupTime -ComputerName $server -ErrorAction Stop |
Select CSName, @{Name="UpTimeHours";Expression={(New-TimeSpan -Start $_.ConvertToDateTime($_.lastbootuptime) -End $(Get-Date)).Hours}}
$uptime = $os | Select -ExpandProperty UpTimeHours
$msg = $null
}
catch {
$uptime = $null
$msg = "WMI Failure. {0}" -f $_.Exception.Message
}
}
else {
$uptime = $null
$msg = "Server offline. Ping failure."
}
$props = @{
ComputerName = $server;
UpTimeInHours = $uptime;
Message = $msg;
}
New-Object -TypeName PSObject -Property $props
}
$serversNoReboot = $results | Where{$_.UpTimeInHours -ge 1}
if ($serversNoReboot) {
$serversNoRebootHTML = $serversNoReboot | Select ComputerName, UpTimeInHours | ConvertTo-HTML -Head "Server Reboot Failure"
$mailParams = @{
To = "kelly.farrell@company.com"
From = "monitor@company.com"
Subject = "Server Uptime"
Body = $serversNoRebootHTML
SmtpServer = "exchange.internal.company.com"
}
Send-MailMessage @mailParams
}
I tried that but I get this:
Send-MailMessage : Cannot convert ‘System.Object’ to the type ‘System.String’
required by parameter ‘Body’. Specified method is not supported.
At C:\Users\kefarrell\Documents\Scripts\reboot-citrix-servers.ps1:47 char:22
I think the issue is Line 43 should be BodyAsHtml = $serversNoRebootHTML
darn now I’m getting -
PS C:\Windows\system32> C:\Users\kefarrell\Documents\Scripts\reboot-email-test.ps1
Send-MailMessage : Cannot convert ‘System.Object’ to the type
‘System.Management.Automation.SwitchParameter’ required by parameter
‘BodyAsHtml’.
At C:\Users\kefarrell\Documents\Scripts\reboot-email-test.ps1:47 char:22
bodyashtml is a switch. body is a string
$serversNoRebootHTML = $serversNoReboot | Select ComputerName, UpTimeInHours | ConvertTo-HTML -Head “Server Reboot Failure” | out-string
$mailParams = @{
To = ‘kelly.farrell@company.com’
From = ‘monitor@company.com’
Subject = ‘Server Uptime’
Body = $serversNoRebootHTML | Out-String
SmtpServer = ‘exchange.internal.company.com’
BodyAsHtml = $true
}
Send-MailMessage @mailParams
I tried replying to this the other day and the forum would log me out every time I went to this thread. Grrr.
Dan covered it, but you simply need to do Out-String:
Body = $serversNoRebootHTML | Out-String