How to: send an email when a server reboots…including who and why!

So, I was told that this might make a good blog post, so thought I’d be a good person and share (because that’s the kind of person I am).

A bit of background: If you follow me on Twitter (and you totally should), over the last few days you may have seen me wearing my ranty pants due to some issues at work. Specifically, regarding a coworker rebooting production domain controllers during the middle of the day with no warning. No IM to the rest of the team to let us know. No email to inform us. Nothing.

Now, I can hear what you want to yell at me: “But if you’ve got your domain set up properly, it shouldn’t be an issue! With multiple domain controllers, there’s redundancy!” You’d be partially right. There is redundancy for the domain. But not for the apps that connect to the domain…and prefer to speak to a specific server (e.g. for LDAP binds). For the sake of getting past this, let’s say that in my environment I know what I’m talking about and rebooting a DC without any warning is bad juju…forgetting, for a moment, that rebooting any production server during business hours without warning is bad juju.

So, moving on. Because this particular coworker, even after being told to let people know, went and did the same thing again the following day – I decided that action needed to be taken. We needed something that would tell us when these servers were going down – sure, monitoring helps, but if the server goes down and comes back up so quickly that your monitoring doesn’t catch it, it makes it hard.

So I went hunting for something that would do what I was after…and I was able to find something that was close, and then kind of smooshed it into what I needed it to do.

So, here goes:

This is a fairly basic script, that I pared down from this one, from when I went hunting. The comments really tell the story – it gets the last EventiD 1074 entry in the System event log, parses that and turns it into individual variables. You put in your email address for To/From, punch in an SMTP server, and it spits out an email with the details of the EventID 1074. Pretty simple.

The following is the script I used. You can also download it here.

# Look for the last event with EventID 1074 in the System log.
$EventInfo = Get-WinEvent -FilterHashtable @{logname='System'; id=1074} -MaxEvents 1
$EventInfo | ForEach-Object {
$rv = New-Object PSObject | Select-Object Date, User, Action, Process, Reason, ReasonCode, Comment
$rv.Date = $_.TimeCreated
$rv.User = $_.Properties[6].Value
$rv.Process = $_.Properties[0].Value
$rv.Action = $_.Properties[4].Value
$rv.Reason = $_.Properties[2].Value
$rv.ReasonCode = $_.Properties[3].Value
$rv.Comment = $_.Properties[5].Value
$rv
}
 
 
# Set your email settings
$From = <INSERT EMAIL ADDRESS HERE>
$To = <INSERT EMAIL ADDRESS HERE>
#$Cc = ""
$Subject = $env:COMPUTERNAME + " has Rebooted"
#My Email body contains custom properties that will differ from your system.
$Body = "$env:COMPUTERNAME has rebooted at $($rv.Date) by $($rv.User) `r`nReason: $($rv.Reason) ($($rv.ReasonCode)) `r`nComment:$($rv.Comment) "
$SMTPServer = <INSERT SMTP SERVER HERE>
$SMTPPort = "25"
 
 
# Send the email!
Send-MailMessage -From $From -to $To -Subject $Subject -Body $Body -SmtpServer $SMTPServer

Now, all we need to do is put it into a scheduled task. The scheduled task I have set runs this at startup using the local SYSTEM account. Not sure if this is the best way (and if there is a better way, please share, remembering this was a quick throw-together I did in about half an hour!)

The following is the XML for the scheduled task, or you can download the .xml file here.

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
 <RegistrationInfo>
 <Date>2016-05-26T08:09:56.24079</Date>
 <Author>DOMAIN\USERNAME</Author>
 </RegistrationInfo>
 <Triggers>
 <BootTrigger>
 <Enabled>true</Enabled>
 </BootTrigger>
 </Triggers>
 <Principals>
 <Principal id="Author">
 <UserId>S-1-5-18</UserId>
 <RunLevel>HighestAvailable</RunLevel>
 </Principal>
 </Principals>
 <Settings>
 <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
 <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
 <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
 <AllowHardTerminate>true</AllowHardTerminate>
 <StartWhenAvailable>false</StartWhenAvailable>
 <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
 <IdleSettings>
 <StopOnIdleEnd>true</StopOnIdleEnd>
 <RestartOnIdle>false</RestartOnIdle>
 </IdleSettings>
 <AllowStartOnDemand>true</AllowStartOnDemand>
 <Enabled>true</Enabled>
 <Hidden>false</Hidden>
 <RunOnlyIfIdle>false</RunOnlyIfIdle>
 <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
 <UseUnifiedSchedulingEngine>false</UseUnifiedSchedulingEngine>
 <WakeToRun>false</WakeToRun>
 <ExecutionTimeLimit>PT10M</ExecutionTimeLimit>
 <Priority>7</Priority>
 </Settings>
 <Actions Context="Author">
 <Exec>
 <Command>powershell.exe</Command>
 <Arguments><LOCATION OF SCRIPT></Arguments>
 </Exec>
 </Actions>
</Task>

When it runs at startup (or manually, if you want it to!) the following is what you’ll get:

RebootEmail

So that’s it – how to make sure you get an email when a critical server reboots and get the information you need to work out who and why!

16 thoughts on “How to: send an email when a server reboots…including who and why!

    1. girlgerms Post author

      They get rebooted monthly (for patching) and if there’s been issues with updates, then most definitely.

      Other than that, not really. Which is why we need to know when it is happening – because it can have major repercussions for other services.

      Reply
    1. girlgerms Post author

      As I said in the post, just trust me when I said that there are certain applications in my organisation that don’t play nice with multiple DNS servers. While you can point these apps at the domain for DNS, they’ll find one DNS server and stick with it…and no move on to another when the one it’s pointing to goes down.

      It’s much easier to point it at one AD DNS server and know which DNS server it’s pointing to, for service continuity etc. etc.

      Reply
      1. Ryan

        Stephan is talking about putting a software load balance like HAProxy in front of your AD servers. I use HAProxy w/ Keepalived to to have redundant load balancers holding a single virtual IP. This allows services that LDAP bind (email spam filter, PHP web applications, etc) to always be assigned that IP address. HAProxy will do health checks against the servers to know which ones are up or down and appropriately forward the request.

  1. chris

    I like it! Does the 1074 event get thrown at any point in the event of power loss? I’d imagine not, yeah?

    Reply
    1. girlgerms Post author

      I haven’t tested that out yet (certainly something to try!) but I would imagine it probably would, but it would be a System “unexpected shutdown”.

      Reply
    2. HOSSEIN AMERY

      Event ID 1074: “The process X has initiated the restart / shutdown of computer on behalf of user Y for the following reason: Z.” Indicates that an application or a user initiated a restart or shutdown.

      Event ID 1076: “The reason supplied by user X for the last unexpected shutdown of this computer is: Y.” Records when the first user with shutdown privileges logs on to the computer after an unexpected restart or shutdown and supplies a reason for the occurrence.

      Reply
  2. Sanele Mallon

    Hi Jess, we had similar event based alerting with our 2008R2 DCs which stopped working after migrating to 2012R2. Does this work with your 2012 R2 DCs?

    Reply
  3. Chris

    Hi Jess
    Good stuff here – side note, the script is lacking smtp authentication, if you go that route you will need a service account, “system” account for scheduled task won’t work.

    Reply
  4. Biswajit

    Thanks for the great post. The email settings did not work for me. kept getting authentication error, so I borrowed the code for the email from this another blog post here to make it work with the original problem of finding the reboot reason – https://www.netwoven.com/2017/04/28/send-an-e-mail-windows-server-2012-task-scheduler-deprecated-feature-solved/

    $SmtpClient = new-object system.net.mail.smtpClient

    $MailMessage = New-Object system.net.mail.mailmessage

    $SmtpClient.Host = “SMTP.YOURcompany.com”

    $mailmessage.from = (“DoNotReply_ToThisEmail@ YOURcompany.com “)

    $mailmessage.To.add(” Person@ YOURcompany.com , Person2@ YOURcompany.com, …… “)

    $mailmessage.Subject = “Alert Subject”

    $mailmessage.Body = “Alert Body with Instruction to recipients”

    $smtpclient.Send($mailmessage)

    Reply
  5. Nicolas Guzman

    2021 and found this gem, thank you! I just used @Biswajit STMP patch and works like a charm.

    Reply
  6. Andy J

    Thank you for sharing. I made a little adjustment to the script to check if the reboot was withing the last 24 hours as I do not want it to keep sending me email everyday if nothing happened in the last 24 hours. Still need to setup the schedule task to run this script though. Below is the modified script:

    # Look for the last event with EventID 1074 in the System log.
    $EventInfo = Get-WinEvent -FilterHashtable @{logname=’System’; id=1074} -MaxEvents 1
    $EventInfo | ForEach-Object {
    $rv = New-Object PSObject | Select-Object Date, User, Action, Process, Reason, ReasonCode, Comment
    $rv.Date = $_.TimeCreated
    $rv.User = $_.Properties[6].Value
    $rv.Process = $_.Properties[0].Value
    $rv.Action = $_.Properties[4].Value
    $rv.Reason = $_.Properties[2].Value
    $rv.ReasonCode = $_.Properties[3].Value
    $rv.Comment = $_.Properties[5].Value
    $rv
    }

    #Cutofdate in this case is time of RIGHT NOW minus 24 hours, hence minus 1 day
    $CutoffDate = (get-date).AddDays(-1).Date
    Write-Output “Cut off date”
    Write-Output $CutoffDate

    $rebootime = $rv.Date
    Write-Output “Reboot time”
    Write-Output $rebootime

    if ($rebootime -lt $CutoffDate)
    {Write-Output “Reboot Date is older than 1 day”
    # Add your code here
    }
    else {Write-Output “Reboot Date is within 24 hours”

    # Set your email settings
    $From = “ENTER NOREPLY EMAIL ADDRESS HERE”
    $To = “ENTER YOUR EMAIL HERE”
    #$Cc = “”
    $Subject = $env:COMPUTERNAME + ” has REBOOTED”
    #My Email body contains custom properties that will differ from your system.
    $Body = “$env:COMPUTERNAME has rebooted at $($rv.Date) by $($rv.User) `r`nReason: $($rv.Reason) ($($rv.ReasonCode)) `r`nComment:$($rv.Comment) ”
    $SMTPServer = “ENTER YOUR SMTP ADDRESS HERE”
    $SMTPPort = “25”

    # Send the email!
    Send-MailMessage -From $From -to $To -Subject $Subject -Body $Body -SmtpServer $SMTPServer
    }

    #once you are happy with the script, remove the pause below so powershell window won’t stay on screen
    pause

    Reply

Leave a Reply