Pull Servers in an OU uptime and e-mail if more than one day

This topic contains 12 replies, has 5 voices, and was last updated by Profile photo of Kelly Farrell Kelly Farrell 1 month, 3 weeks ago.

  • Author
    Posts
  • #54326
    Profile photo of Kelly Farrell
    Kelly Farrell
    Participant

    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}

  • #54329
    Profile photo of Christian Sandfeld
    Christian Sandfeld
    Participant

    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 ... }
    
  • #54330
    Profile photo of Christian Sandfeld
    Christian Sandfeld
    Participant

    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

  • #54331
    Profile photo of Christian Sandfeld
    Christian Sandfeld
    Participant

    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
        }
    }
    
    • #54334
      Profile photo of Kelly Farrell
      Kelly Farrell
      Participant

      thanks that worked – appreciate your help

  • #54338
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    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
    }
    
  • #54535
    Profile photo of Kelly Farrell
    Kelly Farrell
    Participant

    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
    + Send-MailMessage @mailParams
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [Send-MailMessage], Parameter
    BindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Command
    s.SendMailMessage

  • #54541
    Profile photo of BenH
    BenH
    Participant

    I think the issue is Line 43 should be BodyAsHtml = $serversNoRebootHTML

  • #54618
    Profile photo of Kelly Farrell
    Kelly Farrell
    Participant

    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
    + Send-MailMessage @mailParams
    + ~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [Send-MailMessage], Parameter
    BindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Command
    s.SendMailMessage

  • #54621
    Profile photo of Dan Potter
    Dan Potter
    Participant

    bodyashtml is a switch. body is a string

    $serversNoRebootHTML = $serversNoReboot | Select ComputerName, UpTimeInHours | ConvertTo-HTML -Head "Server Reboot Failure" | out-string

  • #54622
    Profile photo of Dan Potter
    Dan Potter
    Participant

    $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

  • #54628
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    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
    
  • #55160
    Profile photo of Kelly Farrell
    Kelly Farrell
    Participant

    thanks that worked

You must be logged in to reply to this topic.