Veeam Backup stats report for all your VM Backup jobs in PowerShell


The other day I was asked to collect some statistics on our Veeam Backup & Recovery server from as many VM Backup jobs as possible. The environment has roughly 70 scheduled jobs thats run either daily or weekly. After searching around a bit first I could not find any current solution or built in method to retrieve the info I needed to collect in a quick or automated way. First ideas were to either somehow grab the info via SQL queries from the Veeam database, or to rather take a sampling of 10-20 different types of jobs and their backup sessions over one normal incremental run day, and one normal full backup day (Manually collecting this data from email reports would be quite a slow process).


After browsing around the Veeam Community Forums I suddenly remembered that there was a PowerShell module that Veeam Include with B&R. I read the basic documentation and got acquainted with a few simple cmdlets.  I wanted to build a report, that would loop through every single Veeam B&R Job we have, and grab data from the last 7 backup sessions of each (daily backups), therefore giving me a good idea of both full backup and incremental backup runs performance, times taken etc… My first attempt at a script got me almost all the way there (tried during spare time in my evenings!) – I was however having trouble matching backup session data with the right day’s backup file stats – sometimes the ordering was out, and I would get metrics back for a backup file that was not from the correct day. Before I was able to resolve this myself, help arrived from “ThomasMc” over at the Veeam Community Forums. (Thanks Thomas!) We got a script together that was able to match up sessions correctly. I then added a few more features, as well as some nice HTML formatting and the ability to grab statistics for all jobs instead of just one sample job. The resulting script gets the following info for you:


  • Index (1 = the last backup sesion, 2 = the day before that, etc)
  • Job Name
  • Start time of job
  • Stop time of job
  • File Name (Allows you to determine if the job was a full or incremental run)
  • Creation Time
  • Average Speed MB – average processing speed of the job
  • Duration – time the job took to complete
  • Result – Success/Warning/Failed (Failed is highlighted in red)


Here is an example of the report run on my Veeam Backup & Recovery Lab environment at home (Thanks to Veeam for the NFR licenses they gave out to VCPs earlier this year!)

[download id=”1″]
[download id=”8″]


So, to run the above script, launch a PowerShell session from within Veeam B&R (Tools -> PowerShell). This will make sure your PowerShell session launches with the Veeam Automation/PowerShell snapin. Execute the script and you’ll get an HTML file output to the root of your C:\ drive. By default, all jobs you have in Veeam will be detailed. If you wish to sample a specific job, or a job with a certain word/phrase in it, adjust the -match parameter for the Get-VBRJob cmdlet line near the top of the script. The default setting is an empty string – i.e. “”. To change how many sessions the the script fetches for each backup job, just change the “$sessionstofetch” variable defined at the top of the script.
I have added comments throughout the script for those interested in how it works. Lastly, you could also quite easily modify this script to e-mail you the report, or even run it as a scheduled task. Let me know if you need help doing this and I’ll gladly modify it as required.


43 thoughts on “Veeam Backup stats report for all your VM Backup jobs in PowerShell”

  1. Has anyone got this to work with v8. i am getting the following error when trying to run script.

    PS C:\scripts> .\Veeam-Backup-Report-v6.ps1
    .\Veeam-Backup-Report-v6.ps1 : File C:\scripts\Veeam-Backup-Report-v6.ps1
    cannot be loaded. The file C:\scripts\Veeam-Backup-Report-v6.ps1 is not
    digitally signed. The script will not execute on the system. For more
    information, see about_Execution_Policies at
    At line:1 char:1
    + .\Veeam-Backup-Report-v6.ps1
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : SecurityError: (:) [], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess

    PS C:\scripts> .\Veeam-Backup-Report.ps1
    .\Veeam-Backup-Report.ps1 : File C:\scripts\Veeam-Backup-Report.ps1 cannot be
    loaded. The file C:\scripts\Veeam-Backup-Report.ps1 is not digitally signed.
    The script will not execute on the system. For more information, see
    about_Execution_Policies at
    At line:1 char:1
    + .\Veeam-Backup-Report.ps1
    + ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : SecurityError: (:) [], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess
    PS C:\scripts>

    Thanks, Lorenzo

  2. Has anyone figured out how to modify this for v7? It works for the most part but it keeps giving me errors on line 72 for the $points variable.

    Also, how can this modified for only showing the most recent job instead of the last 7? I found where to change it from 7 to 1 in the script, but doing that messes up the formatting and takes it out of alphabetical order and makes it messy looking.

  3. Hi Sean..

    sorry for not posting back,, I’v solved this with doing a SQL query instead. My problem is solved.

  4. Hi all

    Needing some assistance with PS to email the result of an inventory job status when run – eg WARNING / PASS / FAIL

    Code i’ve got so far as follows;

    Add-PSSnapin VeeamPSSnapin
    $smtpserver = “my.mail.server”
    $from = “”
    $to = “”
    $subject = “Veeam Inventory & Tape Erase”
    $body = Get-VBRTapeDrive | Start-VBRTapeInventory | out-string
    $body += Get-VBRTapeMedium -Online | Erase-VBRTapeMedium -Confirm:$false | out-string
    $InventoryResult = “-Result VBRSessionResult”
    $mailer = new-object Net.Mail.SMTPclient($smtpserver)
    $msg = new-object Net.Mail.MailMessage($from,$to,$subject,$InventoryResult)
    $msg.IsBodyHTML = $true

  5. @Marko

    Hi Marko,

    It’s a bit difficult for me to see what you mean, but I assume you are looking for the same report format, but for each VM’s backup status (failed or success) within each of your 3 jobs which now run on folders in vCenter?

    If that is the case you’ll need to do some digging into the Veeam B&R cmdlets for PowerShell I’m afraid! The script above works on a per job basis. I haven’t had the opportunity to touch Veeam Backup in ages now (different job, role etc…), and don’t have access to their latest PowerShell cmdlets to see what would be involved.

    What I generally like to do though is get a list of PowerShell cmdlets, look for something that looks like it might do the job, and then just run the built-in help cmdlets against it. For example:

    Get-Help Get-CustomCmdletGoesHere -Examples


  6. Sean.. I need your help… we have redone all the backups now. to just take backup of the folder from v-center. so I just have 3 jobs.. So I need to get out all the vm’s from that folder, and then as you have here in your report. I that easy to fix?

  7. Dries :
    Can you explain how you solved your PartI ?

    $Jobs = Get-VBRJob | ?{$_.Name -match “JOB*”}

    Question, has anyone redone this script so that it can get all the VM’s from one job?

  8. Hey Sean

    Thx for the script!
    If you add this on top you can use from any PS console.
    # Load Veeam Snap-In
    Add-PsSnapin -Name VeeamPSSnapIn -ErrorAction SilentlyContinue


  9. There sure is – all you’ll need to do is keep track of the figures of each backup in the foreach loop, to have a rolling sum, then divide by the number of backups to get your average. Take a look at the current script and see where you can get the size of each backup property, and add that to your rolling sum, E.g. $sum += $job.Size (in the loop). Then outside of the loop, do something like $avg = $sum / $jobs.Count

    Hope that helps!

  10. Hi, I have made a little changes for run into v7 version and report tape backup also.

    At line 12 change :

    $Jobs = Get-VBRJob | ?{$_.Name -match “”}


    $Jobs = Get-VBRJob | ?{$_.Name -match “”}
    $TJobs = Get-VBRTapeJob | ?{$_.Name -match “”}

    At line 14 change :

    foreach ($job in $Jobs) {


    foreach ($job in $Jobs+$TJobs) {

    At line 41 change:

    $session = Get-VBRBackupSession | ?{$_.JobId -eq $job.Id} | %{


    $session = [Veeam.Backup.Core.CBackupSession]::GetByJob($job.Id) | %{

    With these changes the report works with any kind of jobs.

    Best Regards.

  11. I was wondering if there was a way to get the average size of the backups this way we can look at the report and figure out on average how much space each new backup will take.

  12. @Marko
    Works now, I had to change both of the rows:

    $interestingsess = $table | Where { ($_.StartTime) -gt (Get-Date 2014-01-01)}
    $points = $backup.GetStorages() | sort CreationTime -descending | Where-Object {$_.CreationTime -gt “2014-01-01”}

    Thanks for the help, keep up the good work 😉

  13. Well I’m not sure if it’s only using that part
    $interestingsess = $table | Sort StartTime -descending | select -First 7
    due a fue rows down I find this
    $points = $backup.GetStorages() | sort CreationTime -descending | Select -First 7

  14. @Marko

    Hi Marko,

    Well done on sorting out the first part. You should be able to get all jobs since 01-01-2014. What you’ll want to do, if its using that part, is filter out anything over 01-01-2014. You can use a where clause to this on that line, provided the property “StartTime” is a “DateTime” object.

    For example you could change the line to this:

    $interestingsess = $table | Where { ($_.StartTime) -gt (Get-Date 2014-01-01)

    If you do (Get-Date 2014-01-01).GetType() you’ll see what I mean – this returns a “DateTime” object, and to compare this to the StartTime property in your row’s table, this also needs to be a DateTime object (in other words $row.StartTime.GetType() needs to also return a datetime.) I can’t remember if this is the case off hand, and I don’t have anywhere to run this and check now, but give the above a try and see if that helps.


  15. @Marko
    That part I did solve my self =) thanks anyway 😉

    But one other thing, If I want to get ALL jobs from one date to now.. the part
    $interestingsess = $table | Sort StartTime -descending | select -First 7
    Can this be done so that it will get all jobs from 01-01-2014?

  16. Hi Sean,
    I’m a beginner in PS, and I like this script a lot, nice work.
    The part of changing so I just can get one job or so I realy don’t get that part. The thing is that we are running 40 jobs ao I want one report per job..

  17. Hi Jeff,

    Thanks for the feedback. Sorry to hear it doesn’t work for tape backup jobs. I created this quite a while back for Veeam v.5 as far as I remember so I guess its expected. If I ever get to use Veeam in production again then I’ll look into updating it to work, otherwise if you get the chance, have a play with PowerShell and the Veeam snapin, and see what you can find – it might be a simple property change required to fix 🙂


  18. @Sean

    I tried running this PS script on a Veeam Server (v7.0.0.764) running Tape backup jobs using Veeam Server v7 and it produces a blank HTML page with no tables containing any info about the results of the tape jobs. This script runs as is on Veeam Servers running non tape jobs. We use this script everyday! Thanks for your time creating this.

  19. Just to update on my comments above i have now tested with v7 and works brilliantly as mentioned… however it doesnt seem to be able to report on the status of a “continuous” backup job, if the last “run” has a Failed status, the script above still reports the status of “None”.. just as it does if the script is run and a backup is still in “progress”.. i wish i had the knowledge to tweak so if the status is “None” it says “Running” instead and also to add the ability to report on a continuous backup… if anyone feels brave enough im happy to test! 🙂

  20. Hi Kenneth,

    Thanks for the comment:) I haven’t tried with tape jobs and don’t have any way of testing these myself – best thing to do would be to just run the script against an environment with one setup. Its all read-only info so nothing can be modified by the script.


  21. Hi Chad,

    I have not tested it on the latest version – I don’t use Veeam in my day to day role any more. If I get a chance I will test it out again, otherwise, no harm in giving it a go and letting me know if you get a chance 🙂


  22. Hi Ed,

    Glad you got it up and running. Nice addition with the SMTP mailing functionality 🙂 One thing I have noticed is that the indexed entries of job sessions after a particular job session that failed can sometimes report back inaccurate information. For example, say you fetch the last 7 sessions of a particular job, if session 4 happens to be a failure, the sessions after 4 might be inaccurate. So just one thing to be careful of. I haven’t had the time to address that little bug yet, but hopefully someone on the forums might be able to!


  23. Love the report!

    We wanted this report emailed to us daily, so I just added this code to the end:

    $smtpserver = “”
    $subject=”Awesome Veeam Job Report”
    $body= (Get-Content c:\Veeam-Backup-Report.htm )
    $mailer = new-object Net.Mail.SMTPclient($smtpserver)
    $msg = new-object Net.Mail.MailMessage($from,$to,$subject,$body)
    $msg.IsBodyHTML = $true

    Thanks for the great script!

  24. Hi Nils,

    Great to see you got it working – I’ll try this out again in my lab and see if I can find the difference between your’s and mine. I have updated my lab to v6 so hopefully this script is still compatible.


  25. Hi,

    Not at the moment. To be honest, I haven’t really played with Veeam B&R’s Replica jobs myself. There is bound to be a cmdlet, or set of cmdlets that will pull this info in their snapin though. If I get a chance to take a look I’ll definitely post something up 🙂


  26. Hi,
    Any script to list the Replica Jobs in detailed, such as job, type, name, status, result, target, target LUN Size / free size?


  27. Hi Sean,

    sorry for the delay, but I was yesterday out of office.
    It seems that the following lines generate the errors
    $row.StartTime = $_.Info.CreationTime
    $row.StopTime = $_.Info.EndTime
    $row.Duration = ‘{0:00}:{1:00}:{2:00}’ …

    If I put these lines into comment, via #, the script is running fine. Maybe some identifier or so have changed.

    Veeam is running on Windows 2008 R2 with german language, but i doubt that the language pack would change any identifier in powershell.

    I’ll do some testing at the weekend.



  28. @Nils Jasperneite

    Hi again Nils,

    Could you try and comment out that line of the script (46 in your case). Does it run with that commented out? Did you change anything else in the script, or are you running it exactly how you got it from the download?

    Also, have you made sure you are running it from the Veeam PowerShell environment? In Veeam, go to Tools->PowerShell to ensure the right module is loaded for the script. Otherwise you can also add an Import-Module line at the top of the script to import it yourself if you are running it in the vanilla PowerShell 2.0 prompt.


  29. Hi Nils,

    Which version of Veeam B&R are you running? I have only tested it with the latest release (, so it could be related to some functionality (bits of schema) missing in the Veeam SQL DB on an older version that you are experiencing. Otherwise, if you are on this version, does commenting out this line with a hash (#) allow the script to complete? The report would then be missing this bit of info for each backup session, but it will allow us to see if there are any other errors other than this one line.


  30. Hi Sean,

    tried to use your script. But im always getting erros like

    Exception while setting “StopTime”: “The row ‘StopTime’ can not be set to Null. Use DBNull instead.”
    Bei C:\Downloads\Veeam-Backup-Report.ps1:46 Zeichen:18
    + $row. <<<< StopTime = $_.Info.EndTime
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException

    (Error message is translated from german. Don't know if it's the orignal englisch error message)

    I think $_.Info. seems not to deliver any data.

    Maybe I'm missing some prerequisites.

    Any help is appreciated.



Leave a Comment