{"id":690,"date":"2015-11-07T12:50:39","date_gmt":"2015-11-07T12:50:39","guid":{"rendered":"http:\/\/virtualworlduk.co.uk\/?p=690"},"modified":"2015-11-07T12:50:39","modified_gmt":"2015-11-07T12:50:39","slug":"3-day-veeam-backup-report-powercli","status":"publish","type":"post","link":"https:\/\/www.virtualworlduk.co.uk\/wordp\/3-day-veeam-backup-report-powercli\/","title":{"rendered":"3 day Veeam Backup Report &#8211; Powercli"},"content":{"rendered":"<p>Just to confirm that I am, by no means, a Powercli (PowerShell) expert and would still class myself as a novice. \u00a0With this in mind there are probably tips and better ways to perform some of the items involved in my scripts&#8230; but the items that I have done seem to work for me and may help someone else in the process.<\/p>\n<p>The script enclosed below is a a module that can be added to the &#8216;SysAdmin Modular Report&#8217; that was created by &#8216;TheAgreeableCow&#8217; and featured on Veeams community forums&#8230; links below:<\/p>\n<p><a href=\"http:\/\/www.theagreeablecow.com\/2012\/09\/sysadmin-modular-reporting-samreports.html\">http:\/\/www.theagreeablecow.com\/2012\/09\/sysadmin-modular-reporting-samreports.html<\/a><\/p>\n<p><a href=\"http:\/\/forums.veeam.com\/powershell-f26\/sysadmin-modular-reporting-samreport-for-veeam-t13422.html\">http:\/\/forums.veeam.com\/powershell-f26\/sysadmin-modular-reporting-samreport-for-veeam-t13422.html<\/a><\/p>\n<p>The concept behind SAMReport is taken from some of the work done by Alan Renouf with his vCheck Report: \u00a0<a href=\"http:\/\/www.virtu-al.net\/vcheck-pluginsheaders\/vcheck\/\">http:\/\/www.virtu-al.net\/vcheck-pluginsheaders\/vcheck\/<\/a><\/p>\n<p>Due to wanting to create a table which is colour coded to show whether backups have been successful or failed, I have also utilised code from Martin Pugh called Set-CellColor, this can be found here: \u00a0<a href=\"http:\/\/community.spiceworks.com\/scripts\/show\/2450-change-cell-color-in-html-table-with-powershell-set-cellcolor\">http:\/\/community.spiceworks.com\/scripts\/show\/2450-change-cell-color-in-html-table-with-powershell-set-cellcolor<\/a><\/p>\n<p>&nbsp;<\/p>\n<p><strong>Idea behind the report<\/strong><\/p>\n<p>So the idea behind the report was to make it easier for our backup administrators to perform their daily backup checks and to see whether there had been a failure of a backup over multiple days. \u00a0As with many companies, we have to abide by some Sarbannes-Oxley requirements, with our backups being subject to some of those checks. \u00a0The report checks the last three or four days of Veeam backups and compares them against your virtual machines to produce a report showing the success or failure of the backup over the previous days. \u00a0When a backup is successful, it turns the cell green with Success written in the cell and when it fails, it turns the cell red with Failed written in the cell.<\/p>\n<p>There is also an element that excludes VMs&#8230; firstly it only checks powered on VMs (powered off VMs do not need to be checked on a daily backup check), secondly I use VMware Tags to create a list of Excluded VMs using a Tag Category of &#8216;Backup Tags&#8217;&#8230; this means that any virtual machine which has a Tag assigned to it with the Category &#8216;Backup Tags&#8217; will also be excluded from the report.<\/p>\n<p>As this report will run on a Tuesday through to Sunday to check the backups from the previous three or four nights (we do not have any backups that run on a Sunday), I also introduced a way for the script to change the Saturday backup column to read &#8216;Weekend of <em>date<\/em>&#8216; and check across both Saturday and Sunday\u00a0(just in case a weekly backup has run through to the Sunday).<\/p>\n<p>Anyway, that&#8217;s enough about the idea behind the report, please find enclosed below a view of how the report comes out and also the script:<\/p>\n<p><a href=\"http:\/\/virtualworlduk.co.uk\/wp-content\/uploads\/2015\/11\/Veeam-Report.jpg\"><img fetchpriority=\"high\" decoding=\"async\" class=\"alignnone wp-image-691 size-large\" src=\"http:\/\/virtualworlduk.co.uk\/wp-content\/uploads\/2015\/11\/Veeam-Report-1024x455.jpg\" alt=\"Veeam Report\" width=\"640\" height=\"284\" \/><\/a><\/p>\n<p>[powershell]<\/p>\n<p>asnp &quot;VeeamPSSnapIn&quot; -ErrorAction SilentlyContinue<\/p>\n<p>####################################################################<br \/>\n# Configuration<br \/>\n#<br \/>\n# vCenter server<br \/>\n$Title = &quot;Veeam Protected Machines in Woking&quot;<\/p>\n<p>$vcenter = $VMware_Server<br \/>\n#<br \/>\n# To Exclude VMs from report add VM names to be excluded as fol<br \/>\n# simple wildcards are supported:<br \/>\n# $excludevms=@(&quot;vm1&quot;,&quot;vm2&quot;, &quot;*_replica&quot;)<\/p>\n<p>#$srmvms=@()<\/p>\n<p>#Connect-SrmServer<br \/>\n#$SrmConnection=Connect-SrmServer<br \/>\n#$SrmApi=$SrmConnection.ExtensionData<br \/>\n#$protectionGroups = $srmApi.Protection.ListProtectionGroups()<br \/>\n#$protectionGroups | % {<br \/>\n# $protectionGroup = $_<\/p>\n<p># $protectionGroupInfo = $protectionGroup.GetInfo()<\/p>\n<p># The following command lists the virtual machines associated with a protection group<br \/>\n# $protectedVms = $protectionGroup.ListProtectedVms()<br \/>\n# The result of the above call is an array of references to the virtual machines at the vSphere API<br \/>\n# To populate the data from the vSphere connection, call the UpdateViewData method on each virtual machine view object<br \/>\n# $protectedVms | % { $_.Vm.UpdateViewData() }<br \/>\n# After the data is populated, use it to generate a report<\/p>\n<p># $protectedVms | %{<br \/>\n# select VmName<br \/>\n# $srmvms+=$_.VM.Name<br \/>\n# }<br \/>\n#}<br \/>\n$excludevms=@()<\/p>\n<p>$table = &quot;&quot;<br \/>\n$TableName = &quot;&quot;<br \/>\n$1days = &quot;&quot;<br \/>\n$2days = &quot;&quot;<br \/>\n$3days = &quot;&quot;<br \/>\n$4days = &quot;&quot;<br \/>\n$5days = &quot;&quot;<br \/>\n$6days = &quot;&quot;<br \/>\n$7days = &quot;&quot;<br \/>\n$8days = &quot;&quot;<br \/>\n$9days = &quot;&quot;<br \/>\n####################################################################<\/p>\n<p>Function Set-CellColor<br \/>\n{ &amp;lt;#<br \/>\n.SYNOPSIS<br \/>\nFunction that allows you to set individual cell colors in an HTML table<br \/>\n.DESCRIPTION<br \/>\nTo be used inconjunction with ConvertTo-HTML this simple function allows you<br \/>\nto set particular colors for cells in an HTML table. You provide the criteria<br \/>\nthe script uses to make the determination if a cell should be a particular<br \/>\ncolor (property -gt 5, property -like &quot;*Apple*&quot;, etc).<\/p>\n<p>You can add the function to your scripts, dot source it to load into your current<br \/>\nPowerShell session or add it to your $Profile so it is always available.<\/p>\n<p>To dot source:<br \/>\n.&quot;.\\Set-CellColor.ps1&quot;<\/p>\n<p>.PARAMETER Property<br \/>\nProperty, or column that you will be keying on.<br \/>\n.PARAMETER Color<br \/>\nName or 6-digit hex value of the color you want the cell to be<br \/>\n.PARAMETER InputObject<br \/>\nHTML you want the script to process. This can be entered directly into the<br \/>\nparameter or piped to the function.<br \/>\n.PARAMETER Filter<br \/>\nSpecifies a query to determine if a cell should have its color changed. $true<br \/>\nresults will make the color change while $false result will return nothing.<\/p>\n<p>Syntax<br \/>\n&amp;lt;Property Name&amp;gt; &amp;lt;Operator&amp;gt; &amp;lt;Value&amp;gt;<\/p>\n<p>&amp;lt;Property Name&amp;gt;::= the same as $Property. This must match exactly<br \/>\n&amp;lt;Operator&amp;gt;::= &quot;-eq&quot; | &quot;-le&quot; | &quot;-ge&quot; | &quot;-ne&quot; | &quot;-lt&quot; | &quot;-gt&quot;| &quot;-approx&quot; | &quot;-like&quot; | &quot;-notlike&quot;<br \/>\n&amp;lt;JoinOperator&amp;gt; ::= &quot;-and&quot; | &quot;-or&quot;<br \/>\n&amp;lt;NotOperator&amp;gt; ::= &quot;-not&quot;<\/p>\n<p>The script first attempts to convert the cell to a number, and if it fails it will<br \/>\ncast it as a string. So 40 will be a number and you can use -lt, -gt, etc. But 40%<br \/>\nwould be cast as a string so you could only use -eq, -ne, -like, etc.<br \/>\n.PARAMETER Row<br \/>\nInstructs the script to change the entire row to the specified color instead of the individual cell.<br \/>\n.INPUTS<br \/>\nHTML with table<br \/>\n.OUTPUTS<br \/>\nHTML<br \/>\n.EXAMPLE<br \/>\nget-process | convertto-html | set-cellcolor -Propety cpu -Color red -Filter &quot;cpu -gt 1000&quot; | out-file c:\\test\\get-process.html<\/p>\n<p>Assuming Set-CellColor has been dot sourced, run Get-Process and convert to HTML.<br \/>\nThen change the CPU cell to red only if the CPU field is greater than 1000.<\/p>\n<p>.EXAMPLE<br \/>\nget-process | convertto-html | set-cellcolor cpu red -filter &quot;cpu -gt 1000 -and cpu -lt 2000&quot; | out-file c:\\test\\get-process.html<\/p>\n<p>Same as Example 1, but now we will only turn a cell red if CPU is greater than 100<br \/>\nbut less than 2000.<\/p>\n<p>.EXAMPLE<br \/>\n$HTML = $Data | sort server | ConvertTo-html -head $header | Set-CellColor cookedvalue red -Filter &quot;cookedvalue -gt 1&quot;<br \/>\nPS C:\\&amp;gt; $HTML = $HTML | Set-CellColor Server green -Filter &quot;server -eq &#8216;dc2&#8217;&quot;<br \/>\nPS C:\\&amp;gt; $HTML | Set-CellColor Path Yellow -Filter &quot;Path -like &quot;&quot;*memory*&quot;&quot;&quot; | Out-File c:\\Test\\colortest.html<\/p>\n<p>Takes a collection of objects in $Data, sorts on the property Server and converts to HTML. From there<br \/>\nwe set the &quot;CookedValue&quot; property to red if it&#8217;s greater then 1. We then send the HTML through Set-CellColor<br \/>\nagain, this time setting the Server cell to green if it&#8217;s &quot;dc2&quot;. One more time through Set-CellColor<br \/>\nturns the Path cell to Yellow if it contains the word &quot;memory&quot; in it.<\/p>\n<p>.EXAMPLE<br \/>\n$HTML = $Data | sort server | ConvertTo-html -head $header | Set-CellColor cookedvalue red -Filter &quot;cookedvalue -gt 1&quot; -Row<\/p>\n<p>Now, if the cookedvalue property is greater than 1 the function will highlight the entire row red.<\/p>\n<p>.NOTES<br \/>\nAuthor: Martin Pugh<br \/>\nTwitter: @thesurlyadm1n<br \/>\nSpiceworks: Martin9700<br \/>\nBlog: www.thesurlyadmin.com<\/p>\n<p>Changelog:<br \/>\n1.5 Added ability to set row color with -Row switch instead of the individual cell<br \/>\n1.03 Added error message in case the $Property field cannot be found in the table header<br \/>\n1.02 Added some additional text to help. Added some error trapping around $Filter<br \/>\ncreation.<br \/>\n1.01 Added verbose output<br \/>\n1.0 Initial Release<br \/>\n.LINK<br \/>\nhttp:\/\/community.spiceworks.com\/scripts\/show\/2450-change-cell-color-in-html-table-with-powershell-set-cellcolor<br \/>\n#&amp;gt;<\/p>\n<p>[CmdletBinding()]<br \/>\nParam (<br \/>\n[Parameter(Mandatory=$true,Position=0)]<br \/>\n[string]$Property,<br \/>\n[Parameter(Mandatory=$true,Position=1)]<br \/>\n[string]$Color,<br \/>\n[Parameter(Mandatory=$true,ValueFromPipeline=$true)]<br \/>\n[Object[]]$InputObject,<br \/>\n[Parameter(Mandatory=$true)]<br \/>\n[string]$Filter,<br \/>\n[switch]$Row<br \/>\n)<\/p>\n<p>Begin {<br \/>\nWrite-Verbose &quot;$(Get-Date): Function Set-CellColor begins&quot;<br \/>\nIf ($Filter)<br \/>\n{ If ($Filter.ToUpper().IndexOf($Property.ToUpper()) -ge 0)<br \/>\n{ $Filter = $Filter.ToUpper().Replace($Property.ToUpper(),&quot;`$Value&quot;)<br \/>\nTry {<br \/>\n[scriptblock]$Filter = [scriptblock]::Create($Filter)<br \/>\n}<br \/>\nCatch {<br \/>\nWrite-Warning &quot;$(Get-Date): &quot;&quot;$Filter&quot;&quot; caused an error, stopping script!&quot;<br \/>\nWrite-Warning $Error[0]<br \/>\nExit<br \/>\n}<br \/>\n}<br \/>\nElse<br \/>\n{ Write-Warning &quot;Could not locate $Property in the Filter, which is required. Filter: $Filter&quot;<br \/>\nExit<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>Process {<br \/>\nForEach ($Line in $InputObject)<br \/>\n{ If ($Line.IndexOf(&quot;&amp;lt;tr&amp;gt;&amp;lt;th&quot;) -ge 0)<br \/>\n{ Write-Verbose &quot;$(Get-Date): Processing headers&#8230;&quot;<br \/>\n$Search = $Line | Select-String -Pattern &#8216;&amp;lt;th ?[a-z\\-:;&quot;=]*&amp;gt;(.*?)&amp;lt;\\\/th&amp;gt;&#8217; -AllMatches<br \/>\n$Index = 0<br \/>\nForEach ($Match in $Search.Matches)<br \/>\n{ If ($Match.Groups[1].Value -eq $Property)<br \/>\n{ Break<br \/>\n}<br \/>\n$Index ++<br \/>\n}<br \/>\nIf ($Index -eq $Search.Matches.Count)<br \/>\n{ Write-Warning &quot;$(Get-Date): Unable to locate property: $Property in table header&quot;<br \/>\nExit<br \/>\n}<br \/>\nWrite-Verbose &quot;$(Get-Date): $Property column found at index: $Index&quot;<br \/>\n}<br \/>\nIf ($Line -match &quot;&amp;lt;tr( style=&quot;&quot;background-color:.+?&quot;&quot;)?&amp;gt;&amp;lt;td&quot;)<br \/>\n{ $Search = $Line | Select-String -Pattern &#8216;&amp;lt;td ?[a-z\\-:;&quot;=]*&amp;gt;(.*?)&amp;lt;\\\/td&amp;gt;&#8217; -AllMatches<br \/>\n$Value = $Search.Matches[$Index].Groups[1].Value -as [double]<br \/>\nIf (-not $Value)<br \/>\n{ $Value = $Search.Matches[$Index].Groups[1].Value<br \/>\n}<br \/>\nIf (Invoke-Command $Filter)<br \/>\n{ If ($Row)<br \/>\n{ Write-Verbose &quot;$(Get-Date): Criteria met! Changing row to $Color&#8230;&quot;<br \/>\nIf ($Line -match &quot;&amp;lt;tr style=&quot;&quot;background-color:(.+?)&quot;&quot;&amp;gt;&quot;)<br \/>\n{ $Line = $Line -replace &quot;&amp;lt;tr style=&quot;&quot;background-color:$($Matches[1])&quot;,&quot;&amp;lt;tr style=&quot;&quot;background-color:$Color&quot;<br \/>\n}<br \/>\nElse<br \/>\n{ $Line = $Line.Replace(&quot;&amp;lt;tr&amp;gt;&quot;,&quot;&amp;lt;tr style=&quot;&quot;background-color:$Color&quot;&quot;&amp;gt;&quot;)<br \/>\n}<br \/>\n}<br \/>\nElse<br \/>\n{ Write-Verbose &quot;$(Get-Date): Criteria met! Changing cell to $Color&#8230;&quot;<br \/>\n$Line = $Line.Replace($Search.Matches[$Index].Value,&quot;&amp;lt;td style=&quot;&quot;background-color:$Color&quot;&quot;&amp;gt;$Value&amp;lt;\/td&amp;gt;&quot;)<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\nWrite-Output $Line<br \/>\n}<br \/>\n}<\/p>\n<p>End {<br \/>\nWrite-Verbose &quot;$(Get-Date): Function Set-CellColor completed&quot;<br \/>\n}<br \/>\n}<\/p>\n<p>$vcenterobj = Get-VBRServer -Name $vcenter<br \/>\nNew-VIProperty -Name Tag -ObjectType VirtualMachine -Value { Get-TagAssignment -Entity $args[0] -Category &quot;&quot; | select -ExpandProperty Tag }<br \/>\n$excludevms=@(get-tagassignment -Category &#8216;Backup Tags&#8217; | select -property @{N=&#8217;VM&#8217;;E={$_.Entity}})<\/p>\n<p>$FullVM = Get-vm | Where-Object {$_.PowerState -eq &quot;PoweredOn&quot; -and $_ -notin $excludevms.VM.Name}<\/p>\n<p># Get a list of all VMs from vCenter and add to hash table, assume Unprotected<br \/>\n$Result=@()<br \/>\nforeach ($vm in ($FullVM | ForEach-Object {$_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$vm | Add-Member -MemberType NoteProperty -Name &quot;backed_up&quot; -Value $False<br \/>\n$vm | Add-Member -MemberType NoteProperty -Name &quot;backed_up2&quot; -Value $False<br \/>\n$vm | Add-Member -MemberType NoteProperty -Name &quot;backed_up3&quot; -Value $False<br \/>\n$vm | Add-Member -MemberType NoteProperty -Name &quot;backed_up4&quot; -Value $False<\/p>\n<p>$Result += $vm<br \/>\n# }<br \/>\n}<br \/>\n# Find all backup job sessions that have ended in the last week<br \/>\n$vbrsessions = &quot;&quot;<\/p>\n<p>if ([DateTime]::Today.AddDays(-1).DayOfWeek -eq &quot;Saturday&quot;) {<\/p>\n<p>$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq &quot;Backup&quot; -or $_.JobType -eq &quot;Replica&quot; -and $_.EndTime -ge [DateTime]::Today.AddDays(-1).AddHours(05) -and $_.EndTime -lt [DateTime]::Today.AddHours(23) -and $_ -notin $excludevms.VM.Name}<\/p>\n<p>foreach ($session in $vbrsessions) {<br \/>\nforeach ($vm in ($session.gettasksessions() | ForEach-Object { $_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$VMObj = $Result | where {$_.VMName -eq $vm.VMname }<br \/>\nif ($VMObj){<br \/>\n$VMObj.backed_up = $True<\/p>\n<p>}<\/p>\n<p>}<br \/>\n}<\/p>\n<p>}<\/p>\n<p>if ([DateTime]::Today.AddDays(-1).DayOfWeek -eq &quot;Friday&quot;) {<\/p>\n<p>$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq &quot;Backup&quot; -or $_.JobType -eq &quot;Replica&quot; -and $_.EndTime -ge [DateTime]::Today.AddDays(-1).AddHours(17) -and $_.EndTime -lt [DateTime]::Today.AddHours(04) -and $_ -notin $excludevms.VM.Name}<\/p>\n<p>foreach ($session in $vbrsessions) {<br \/>\nforeach ($vm in ($session.gettasksessions() | ForEach-Object { $_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$VMObj = $Result | where {$_.VMName -eq $vm.VMname }<br \/>\nif ($VMObj){<br \/>\n$VMObj.backed_up = $True<\/p>\n<p>}<\/p>\n<p>}<br \/>\n}<\/p>\n<p>}<\/p>\n<p>if ([DateTime]::Today.AddDays(-1).DayOfWeek -eq &quot;Sunday&quot;) {<\/p>\n<p>}<\/p>\n<p>if ([DateTime]::Today.AddDays(-1).DayOfWeek -ne &quot;Saturday&quot; -or &quot;Sunday&quot;){<br \/>\n$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq &quot;Backup&quot; -or $_.JobType -eq &quot;Replica&quot; -and $_.EndTime -ge [DateTime]::Today.AddDays(-1).AddHours(17) -and $_.EndTime -lt [DateTime]::Today.AddHours(15) -and $_ -notin $excludevms.VM.Name}<\/p>\n<p>foreach ($session in $vbrsessions) {<br \/>\nforeach ($vm in ($session.gettasksessions() | ForEach-Object { $_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$VMObj = $Result | where {$_.VMName -eq $vm.VMname }<br \/>\nif ($VMObj){<br \/>\n$VMObj.backed_up = $True<\/p>\n<p>}<\/p>\n<p>}<br \/>\n}<br \/>\n}<br \/>\nif ([DateTime]::Today.AddDays(-2).DayOfWeek -eq &quot;Saturday&quot;) {<\/p>\n<p>$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq &quot;Backup&quot; -or $_.JobType -eq &quot;Replica&quot; -and $_.EndTime -ge [DateTime]::Today.AddDays(-2).AddHours(05) -and $_.EndTime -lt [DateTime]::Today.AddDays(-1).AddHours(23) -and $_ -notin $excludevms.VM.Name}<\/p>\n<p>foreach ($session in $vbrsessions) {<br \/>\nforeach ($vm in ($session.gettasksessions() | ForEach-Object { $_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$VMObj = $Result | where {$_.VMName -eq $vm.VMname }<br \/>\nif ($VMObj){<br \/>\n$VMObj.backed_up2 = $True<\/p>\n<p>}<\/p>\n<p>}<br \/>\n}<\/p>\n<p>}<\/p>\n<p># Find all successfully backed up VMs in selected sessions (i.e. VMs not ending in failure) and update status to &quot;Protected&quot;<\/p>\n<p>if ([DateTime]::Today.AddDays(-2).DayOfWeek -eq &quot;Friday&quot;) {<\/p>\n<p>$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq &quot;Backup&quot; -or $_.JobType -eq &quot;Replica&quot; -and $_.EndTime -ge [DateTime]::Today.AddDays(-2).AddHours(17) -and $_.EndTime -lt [DateTime]::Today.AddDays(-1).AddHours(04) -and $_ -notin $excludevms.VM.Name}<\/p>\n<p>foreach ($session in $vbrsessions) {<br \/>\nforeach ($vm in ($session.gettasksessions() | ForEach-Object { $_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$VMObj = $Result | where {$_.VMName -eq $vm.VMname }<br \/>\nif ($VMObj){<br \/>\n$VMObj.backed_up2 = $True<\/p>\n<p>}<\/p>\n<p>}<br \/>\n}<\/p>\n<p>}<\/p>\n<p>if ([DateTime]::Today.AddDays(-2).DayOfWeek -eq &quot;Sunday&quot;) {<\/p>\n<p>}<\/p>\n<p>if ([DateTime]::Today.AddDays(-2).DayOfWeek -ne &quot;Saturday&quot; -or &quot;Sunday&quot;){<br \/>\n$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq &quot;Backup&quot; -or $_.JobType -eq &quot;Replica&quot; -and $_.EndTime -ge [DateTime]::Today.AddDays(-2).AddHours(17) -and $_.EndTime -lt [DateTime]::Today.AddDays(-1).AddHours(15)-and $_ -notin $excludevms.VM.Name}<\/p>\n<p>foreach ($session in $vbrsessions) {<br \/>\nforeach ($vm in ($session.gettasksessions() | ForEach-Object { $_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$VMObj = $Result | where {$_.VMName -eq $vm.VMname }<br \/>\nif ($VMObj){<br \/>\n$VMObj.backed_up2 = $True<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>$vbrsessions = &quot;&quot;<br \/>\nif ([DateTime]::Today.AddDays(-3).DayOfWeek -eq &quot;Saturday&quot;) {<\/p>\n<p>$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq &quot;Backup&quot; -or $_.JobType -eq &quot;Replica&quot; -and $_.EndTime -ge [DateTime]::Today.AddDays(-3).AddHours(05) -and $_.EndTime -lt [DateTime]::Today.AddDays(-2).AddHours(23) -and $_ -notin $excludevms.VM.Name}<\/p>\n<p>foreach ($session in $vbrsessions) {<br \/>\nforeach ($vm in ($session.gettasksessions() | ForEach-Object { $_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$VMObj = $Result | where {$_.VMName -eq $vm.VMname }<br \/>\nif ($VMObj){<br \/>\n$VMObj.backed_up3 = $True<\/p>\n<p>}<\/p>\n<p>}<br \/>\n}<\/p>\n<p>}<\/p>\n<p>if ([DateTime]::Today.AddDays(-3).DayOfWeek -eq &quot;Friday&quot;) {<\/p>\n<p>$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq &quot;Backup&quot; -or $_.JobType -eq &quot;Replica&quot; -and $_.EndTime -ge [DateTime]::Today.AddDays(-3).AddHours(17) -and $_.EndTime -lt [DateTime]::Today.AddDays(-2).AddHours(04) -and $_ -notin $excludevms.VM.Name}<\/p>\n<p>foreach ($session in $vbrsessions) {<br \/>\nforeach ($vm in ($session.gettasksessions() | ForEach-Object { $_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$VMObj = $Result | where {$_.VMName -eq $vm.VMname }<br \/>\nif ($VMObj){<br \/>\n$VMObj.backed_up3 = $True<\/p>\n<p>}<\/p>\n<p>}<br \/>\n}<\/p>\n<p>}<br \/>\nif ([DateTime]::Today.AddDays(-3).DayOfWeek -eq &quot;Sunday&quot;) {<\/p>\n<p>}<\/p>\n<p>if ([DateTime]::Today.AddDays(-3).DayOfWeek -ne &quot;Saturday&quot; -or &quot;Sunday&quot;){<br \/>\n$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq &quot;Backup&quot; -or $_.JobType -eq &quot;Replica&quot; -and $_.EndTime -ge [DateTime]::Today.AddDays(-3).AddHours(17) -and $_.EndTime -lt [DateTime]::Today.AddDays(-2).AddHours(15)-and $_ -notin $excludevms.VM.Name}<\/p>\n<p>foreach ($session in $vbrsessions) {<br \/>\nforeach ($vm in ($session.gettasksessions() | ForEach-Object { $_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$VMObj = $Result | where {$_.VMName -eq $vm.VMname }<br \/>\nif ($VMObj){<br \/>\n$VMObj.backed_up3 = $True<\/p>\n<p>}<\/p>\n<p>}<br \/>\n}<br \/>\n}<\/p>\n<p>$vbrsessions = &quot;&quot;<\/p>\n<p>if ([DateTime]::Today.AddDays(-4).DayOfWeek -eq &quot;Saturday&quot;) {<\/p>\n<p>$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq &quot;Backup&quot; -or $_.JobType -eq &quot;Replica&quot; -and $_.EndTime -ge [DateTime]::Today.AddDays(-4).AddHours(05) -and $_.EndTime -lt [DateTime]::Today.AddDays(-3).AddHours(23) -and $_ -notin $excludevms.VM.Name}<\/p>\n<p>foreach ($session in $vbrsessions) {<br \/>\nforeach ($vm in ($session.gettasksessions() | ForEach-Object { $_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$VMObj = $Result | where {$_.VMName -eq $vm.VMname }<br \/>\nif ($VMObj){<br \/>\n$VMObj.backed_up4 = $True<\/p>\n<p>}<\/p>\n<p>}<br \/>\n}<\/p>\n<p>}<\/p>\n<p>if ([DateTime]::Today.AddDays(-4).DayOfWeek -eq &quot;Friday&quot;) {<\/p>\n<p>$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq &quot;Backup&quot; -or $_.JobType -eq &quot;Replica&quot; -and $_.EndTime -ge [DateTime]::Today.AddDays(-4).AddHours(17) -and $_.EndTime -lt [DateTime]::Today.AddDays(-3).AddHours(04) -and $_ -notin $excludevms.VM.Name}<\/p>\n<p>foreach ($session in $vbrsessions) {<br \/>\nforeach ($vm in ($session.gettasksessions() | ForEach-Object { $_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$VMObj = $Result | where {$_.VMName -eq $vm.VMname }<br \/>\nif ($VMObj){<br \/>\n$VMObj.backed_up4 = $True<\/p>\n<p>}<\/p>\n<p>}<br \/>\n}<\/p>\n<p>}<br \/>\nif ([DateTime]::Today.AddDays(-4).DayOfWeek -eq &quot;Sunday&quot;) {<\/p>\n<p>}<\/p>\n<p>if ([DateTime]::Today.AddDays(-4).DayOfWeek -ne &quot;Saturday&quot; -or &quot;Sunday&quot;){<br \/>\n$vbrsessions = Get-VBRBackupSession | Where-Object {$_.JobType -eq &quot;Backup&quot; -or $_.JobType -eq &quot;Replica&quot; -and $_.EndTime -ge [DateTime]::Today.AddDays(-4).AddHours(17) -and $_.EndTime -lt [DateTime]::Today.AddDays(-3).AddHours(15)-and $_ -notin $excludevms.VM.Name}<\/p>\n<p>foreach ($session in $vbrsessions) {<br \/>\nforeach ($vm in ($session.gettasksessions() | ForEach-Object { $_ | Select-object @{Name=&quot;VMname&quot;;Expression={$_.Name}}})) {<\/p>\n<p>$VMObj = $Result | where {$_.VMName -eq $vm.VMname }<br \/>\nif ($VMObj){<br \/>\n$VMObj.backed_up4 = $True<\/p>\n<p>}<\/p>\n<p>}<br \/>\n}<br \/>\n}<\/p>\n<p>$Comments = &#8216;Comments&#8217;<\/p>\n<p>if ([DateTime]::Today.AddDays(-1).DayOfWeek -eq &quot;Sunday&quot;){<br \/>\n$1days = [DateTime]::Today.AddDays(-1).ToString(&#8216;ddd d MMM yyy&#8217;)<br \/>\n$2days = &#8216;Weekend of &#8216; + [DateTime]::Today.AddDays(-2).ToString(&#8216;d MMM yyy&#8217;)<br \/>\n$3days = [DateTime]::Today.AddDays(-3).ToString(&#8216;ddd d MMM yyy&#8217;)<br \/>\n$4days = [DateTime]::Today.AddDays(-4).ToString(&#8216;ddd d MMM yyy&#8217;)<br \/>\n$TableName = &quot;Backups&quot;<br \/>\n$table = New-Object system.Data.DataTable &quot;$TableName&quot;<br \/>\n$col2 = New-Object system.Data.DataColumn VM, ([string])<br \/>\n$col8 = New-Object system.Data.DataColumn $4days, ([string])<br \/>\n$col9 = New-Object system.Data.DataColumn $3days, ([string])<br \/>\n$col10 = New-Object system.Data.DataColumn $2days, ([string])<br \/>\n$col12 = New-Object system.Data.DataColumn Comments, ([string])<\/p>\n<p>$table.columns.add($col2)<br \/>\n$table.columns.add($col8)<br \/>\n$table.columns.add($col9)<br \/>\n$table.columns.add($col10)<br \/>\n$table.columns.add($col12)<br \/>\nforeach ($vm in $Result) {<\/p>\n<p>$row = $table.NewRow();$row.VM=$vm.VMname;$row.$4days=$vm.backed_up4;$row.$3days=$vm.backed_up3;$row.$2days=$vm.backed_up2;$table.Rows.Add($row)#;$table.Rows.Add($row)<\/p>\n<p>}<\/p>\n<p>$datetoday=get-date -format D<br \/>\n$reportdate=get-date -format &quot;yyyy-MMM-d&quot;<br \/>\n$ResultsText = &quot;The following machines in Woking have been successfully backed up using Veeam in the past &quot; + $AgeAlert + &quot; Day(s)&quot;<br \/>\n$ResultsAlert = &quot;Good&quot;<\/p>\n<p>############################################################################################################<br \/>\n# Output #<br \/>\n#&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/p>\n<p>$OutText = $ResultsText<br \/>\n$OutData = $Table | Select-Object VM,$4days,$3days,$2days,$Comments | Sort-Object VM<br \/>\n$OutAlert = $ResultsAlert<br \/>\n$Attachment = &quot;&quot;<br \/>\n}<\/p>\n<p>if ([DateTime]::Today.AddDays(-2).DayOfWeek -eq &quot;Sunday&quot;){<br \/>\n$1days = [DateTime]::Today.AddDays(-1).ToString(&#8216;ddd d MMM yyy&#8217;)<br \/>\n$2days = [DateTime]::Today.AddDays(-2).ToString(&#8216;ddd d MMM yyy&#8217;)<br \/>\n$3days = &#8216;Weekend of &#8216; + [DateTime]::Today.AddDays(-3).ToString(&#8216;d MMM yyy&#8217;)<br \/>\n$4days = [DateTime]::Today.AddDays(-4).ToString(&#8216;ddd d MMM yyy&#8217;)<br \/>\n$TableName = &quot;Backups&quot;<br \/>\n$table = New-Object system.Data.DataTable &quot;$TableName&quot;<br \/>\n$col2 = New-Object system.Data.DataColumn VM, ([string])<br \/>\n$col8 = New-Object system.Data.DataColumn $4days, ([string])<br \/>\n$col9 = New-Object system.Data.DataColumn $3days, ([string])<br \/>\n$col11 = New-Object system.Data.DataColumn $1days, ([string])<br \/>\n$col12 = New-Object system.Data.DataColumn Comments, ([string])<\/p>\n<p>$table.columns.add($col2)<br \/>\n$table.columns.add($col8)<br \/>\n$table.columns.add($col9)<br \/>\n$table.columns.add($col11)<br \/>\n$table.columns.add($col12)<\/p>\n<p>foreach ($vm in $Result) {<br \/>\n$row = $table.NewRow();$row.VM=$vm.VMname;$row.$4days=$vm.backed_up4;$row.$3days=$vm.backed_up3;$row.$1days=$vm.backed_up;$table.Rows.Add($row)#;$table.Rows.Add($row)<\/p>\n<p>}<\/p>\n<p>$datetoday=get-date -format D<br \/>\n$reportdate=get-date -format &quot;yyyy-MMM-d&quot;<br \/>\n$ResultsText = &quot;The following machines in Woking have been successfully backed up using Veeam in the past &quot; + $AgeAlert + &quot; Day(s)&quot;<br \/>\n$ResultsAlert = &quot;Good&quot;<br \/>\n############################################################################################################<br \/>\n# Output #<br \/>\n#&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/p>\n<p>$OutText = $ResultsText<br \/>\n$OutData = $Table | Select-Object VM,$4days,$3days,$1days,$Comments | Sort-Object VM<br \/>\n$OutAlert = $ResultsAlert<br \/>\n$Attachment = &quot;&quot;<br \/>\n}<\/p>\n<p>if ([DateTime]::Today.AddDays(-3).DayOfWeek -eq &quot;Sunday&quot;){<br \/>\n$1days = [DateTime]::Today.AddDays(-1).ToString(&#8216;ddd d MMM yyy&#8217;)<br \/>\n$2days = [DateTime]::Today.AddDays(-2).ToString(&#8216;ddd d MMM yyy&#8217;)<br \/>\n$3days = [DateTime]::Today.AddDays(-3).ToString(&#8216;ddd d MMM yyy&#8217;)<br \/>\n$4days = &#8216;Weekend of &#8216; + [DateTime]::Today.AddDays(-4).ToString(&#8216;d MMM yyy&#8217;)<br \/>\n$TableName = &quot;Backups&quot;<br \/>\n$table = New-Object system.Data.DataTable &quot;$TableName&quot;<br \/>\n$col2 = New-Object system.Data.DataColumn VM, ([string])<br \/>\n$col8 = New-Object system.Data.DataColumn $4days, ([string])<br \/>\n$col10 = New-Object system.Data.DataColumn $2days, ([string])<br \/>\n$col11 = New-Object system.Data.DataColumn $1days, ([string])<br \/>\n$col12 = New-Object system.Data.DataColumn Comments, ([string])<\/p>\n<p>$table.columns.add($col2)<br \/>\n$table.columns.add($col8)<br \/>\n$table.columns.add($col10)<br \/>\n$table.columns.add($col11)<br \/>\n$table.columns.add($col12)<\/p>\n<p>foreach ($vm in $Result) {<br \/>\n$row = $table.NewRow();$row.VM=$vm.VMname;$row.$4days=$vm.backed_up4;$row.$2days=$vm.backed_up2;$row.$1days=$vm.backed_up;$table.Rows.Add($row)#;$table.Rows.Add($row)<\/p>\n<p>}<br \/>\n$datetoday=get-date -format D<br \/>\n$reportdate=get-date -format &quot;yyyy-MMM-d&quot;<br \/>\n$ResultsText = &quot;The following machines in Woking have been successfully backed up using Veeam in the past &quot; + $AgeAlert + &quot; Day(s)&quot;<br \/>\n$ResultsAlert = &quot;Good&quot;<\/p>\n<p>############################################################################################################<br \/>\n# Output #<br \/>\n#&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/p>\n<p>$OutText = $ResultsText<br \/>\n$OutData = $Table | Select-Object VM,$4days,$2days,$1days,$Comments | Sort-Object VM<br \/>\n$OutAlert = $ResultsAlert<br \/>\n$Attachment = &quot;&quot;<br \/>\n}<\/p>\n<p>if ([DateTime]::Today.AddDays(-4).DayOfWeek -eq &quot;Sunday&quot;){<br \/>\n$1days = [DateTime]::Today.AddDays(-1).ToString(&#8216;ddd d MMM yyy&#8217;)<br \/>\n$2days = [DateTime]::Today.AddDays(-2).ToString(&#8216;ddd d MMM yyy&#8217;)<br \/>\n$3days = [DateTime]::Today.AddDays(-3).ToString(&#8216;ddd d MMM yyy&#8217;)<br \/>\n$4days = [DateTime]::Today.AddDays(-4).ToString(&#8216;ddd d MMM yyy&#8217;)<\/p>\n<p>$TableName = &quot;Backups&quot;<br \/>\n$table = New-Object system.Data.DataTable &quot;$TableName&quot;<br \/>\n$col2 = New-Object system.Data.DataColumn VM, ([string])<br \/>\n$col9 = New-Object system.Data.DataColumn $3days, ([string])<br \/>\n$col10 = New-Object system.Data.DataColumn $2days, ([string])<br \/>\n$col11 = New-Object system.Data.DataColumn $1days, ([string])<br \/>\n$col12 = New-Object system.Data.DataColumn Comments, ([string])<\/p>\n<p>$table.columns.add($col2)<br \/>\n$table.columns.add($col9)<br \/>\n$table.columns.add($col10)<br \/>\n$table.columns.add($col11)<br \/>\n$table.columns.add($col12)<\/p>\n<p>foreach ($vm in $Result) {<br \/>\n$row = $table.NewRow();$row.VM=$vm.VMname;$row.$3days=$vm.backed_up3;$row.$2days=$vm.backed_up2;$row.$1days=$vm.backed_up;$table.Rows.Add($row)#;$table.Rows.Add($row)<\/p>\n<p>}<br \/>\n$datetoday=get-date -format D<br \/>\n$reportdate=get-date -format &quot;yyyy-MMM-d&quot;<br \/>\n$ResultsText = &quot;The following machines in Woking have been successfully backed up using Veeam in the past &quot; + $AgeAlert + &quot; Day(s)&quot;<br \/>\n$ResultsAlert = &quot;Good&quot;<br \/>\n############################################################################################################<br \/>\n# Output #<br \/>\n#&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<\/p>\n<p>$OutText = $ResultsText<br \/>\n$OutData = $Table | Select-Object VM,$3days,$2days,$1days,$Comments | Sort-Object VM<br \/>\n$OutAlert = $ResultsAlert<br \/>\n$Attachment = &quot;&quot;<br \/>\n}<br \/>\n[\/powershell]<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Just to confirm that I am, by no means, a Powercli (PowerShell) expert and would still class myself as a novice. \u00a0With this in mind there are probably tips and better ways to perform some of the items involved in my scripts&#8230; but the items that I have done seem to work for me and may help someone else in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":691,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[9],"tags":[],"class_list":["post-690","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-vmware"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/posts\/690","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/comments?post=690"}],"version-history":[{"count":0,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/posts\/690\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/media?parent=690"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/categories?post=690"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.virtualworlduk.co.uk\/wordp\/wp-json\/wp\/v2\/tags?post=690"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}