Most of my publicly available PowerShell scripts start out by solving my own problem first, before they were cleaned up and released to the world. One of the earliest examples of this is my Get-DailyBackupAlerts.ps1 script, which checks Exchange database backup time stamps and sends an email report to alert you to any that have not recently been backed up. I can’t tell you how many times this script avoided a potential disaster in environments that I managed, and I’ve heard from dozens of other people in the Exchange community that tell me it saved their bacon as well.

Get-DailyBackupAlerts.ps1 was first developed in 2011, and it would have been developed for an Exchange 2007 environment at first. Over time I added support for Exchange 2010 and database availability groups, but after that I only did a few bug fixes and stopped updating the script in 2014 since it just kept working for new versions of Exchange without any changes needed.

This week I had some time to look at the code again. I wanted to update the script so that it handled differential backups (until now it only looked at full and incremental backups), using code that I wrote for Exchange Analyzer. As it turns out, retrofitting the new code to the old script wasn’t as simple as I thought it would be. But it gave me a good excuse to tidy up a bunch of other things that were symptoms of having written the script over five years ago, as well as add a few enhancements that were suggested on GitHub.

And so I am pleased to release V1.07 of Get-DailyBackupAlerts.ps1, which includes:

  • Handling for differential backups
  • Color-coded status in report (alert/OK)
  • Change to calculation of hours since last backup to base it on UTC time, which is more accurate for multi-region environments


You can download the new version of the script from the TechNet Script Gallery or GitHub.

About the Author

Paul Cunningham

Paul is a former Microsoft MVP for Office Apps and Services. He works as a consultant, writer, and trainer specializing in Office 365 and Exchange Server. Paul no longer writes for


  1. Melissa

    I mean edit the settings file.

  2. Melissa

    I am not able to get the exclusions to work. Can you show how to edit the script correctly for exclusions?

  3. Michael Rübel

    Hello Paul,
    first – thanks for your script. But I found an issue. Suppose, you have two databases (DB01 and DB02). DB01 is has incremental backup and DB02 has full backup (weird, but I have some customers doing such an schedule).

    Running the script, the script will circle through the databases. Because DB01 was backed up incrementally, the variable [int]$LastInc = (($now.ToUniversalTime() – $db.LastIncrementalBackup.ToUniversalTime()).TotalHours) will be forced to be of type integer.

    During the next cycle for database DB02, the variable will be set to $LastInc = “Never”, which is of type string – resulting the shell is throwing an error:

    Cannot convert value “Never” to type “System.Int32”. Error: “Input string was not in a correct format.”

    Solution could be [string]$LastInc = “Never”, but casting a variable is so hmmmm

  4. Aatish

    I want to Ignore Public Folders in report. Can you suggest any modification??

  5. Dave

    Hi Paul,

    What would I need to do in order to add a couple of things to the report? Like if I want to add Last Full and Last incremental rather than just reporting the type of backup that was last performed. Look forward to your response.


    1. Avatar photo
      Paul Cunningham

      Feel free to edit the code to suit your requirements. If you’re new to PowerShell it will be an excellent learning experience.

  6. Obi DG

    Any way to to allow for Display name for “From” email address.

    If your previous iteration that we’re been using I was able to enter something like.

    Mail Monitor

    When I try that not I get errors because PS isn’t parsing the that field correctly. I’ve played around with the XML to see if I can add it. I know last resort is just editing the script directly, but thought I’d ask before doing that.

    1. Obi DG


      “In” your previous iteration that we’re been using I was able to enter something like.

    2. Obi DG

      Looks like the fake email from the original post got stripped

      But I would set the display name by have the “From” variable equal

      Mail Monitor

      1. Obi DG

        I just went ahead and edited the script directly and got the desired result.

  7. Shannon

    Hey Paul,

    I see that there is a new script version out there. We had issues with databases not showing as being backed up when Exchange and Barracuda were showing that they were. This was version 1.07 so I reverted back to the previous one and everything was working. I’ve downloaded 1.08 and will see if the issue persists. If there are, do you want me to send the log file over?

      1. Shannoon

        New version (1.08) seems to be working great now. Thanks Paul!

  8. Trevor Procyshen

    We have some old Exchange 2010 test databases that have not been backed up in over 3000 hours yet they are not flagged as an alert by the script, the status shows OK. Any ideas why this might happen?

      1. Trevor Procyshen

        This 1.08 version of the script is working now, the databases backed up long ago are now showing as an Alert status. This time it included the log file in the email as an attachment, I see the section in the script where I can comment this out if not needed. Thanks!

  9. Bruce McKay

    Seems to work ok.
    One enhancement after getting concerned about the last date time stamp in the email, the time was in UTC and we are NZST which is +12 hours.
    Thought there was a backup problem at first glance !

  10. Chris Gecks

    Hi Paul,

    I was wondering if you could help me out. I am running into some issues with the updated Get-DailyBackupAlerts.ps1 V1.07 script.

    You cannot call a method on a null-valued expression.
    At C:PS_ScriptsGet-DailyBackupAlerts.ps1-1.07Get-DailyBackupAlerts.ps1:371 char:5
    + $LatestBackup = ($LastBackups.GetEnumerator() | Sort-Object -Property Value) …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    You cannot call a method on a null-valued expression.
    At C:PS_ScriptsGet-DailyBackupAlerts.ps1-1.07Get-DailyBackupAlerts.ps1:424 char:12
    + elseif ($($LatestBackup.Value.ToInt32($null)) -gt $threshold) {
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    PS C:PS_ScriptsGet-DailyBackupAlerts.ps1-1.07>

    If you have any questions or concerns please let me know.

    Thanks for all your time and help.

    Kindest Regards,
    Chris Gecks

    1. Jose Gonzalez

      For the record: I get the exact same error message.

Leave a Reply