Functions/Get-DPMCXRecoveryPointStatus.ps1

#requires -Version 2.0
function Get-DPMCXRecoveryPointStatus 
{
  [CmdletBinding()]
  param (    
    [ValidateNotNullOrEmpty()]
    [PSCredential] $Credential,
    [Parameter(Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    [ValidateNotNullOrEmpty()]
    [string[]] $DpmServerName = 'localhost',
    [datetime] $OlderThan
  )

  begin {

    $output  = @()

  }


  process {

    Foreach ($computer in $DpmServerName) 
    {
      Write-Verbose -Message "Processing computer $computer"

      Remove-Variable -Name session -ErrorAction Ignore

      $PSSessionParameters = @{

         ComputerName = $computer
         ErrorAction = 'Stop'

      }

      if ($PSBoundParameters.ContainsKey('Credential')) {

         $PSSessionParameters.Add('Credential',$Credential)

      }

      try 
      {
        $session = New-PSSession @PSSessionParameters
      }

      catch 
      {
        $output += New-Object -TypeName pscustomobject -Property @{
          'DPMServer'         = $computer
          'Connection'   = 'Failed'
          'DataSource'        = $null
          'ProtectedComputer' = $null
          'ProtectionGroup'   = $null
          'LatestRecoveryPoint' = $null
          'Status'            = $null
          'Errors'            = "Connection error: $($_.Exception.Message)"
        }
      }

      $InitializeDPMCXDataSourcePropertyDefinition = "function Initialize-DPMCXDataSourceProperty { ${function:Initialize-DPMCXDataSourceProperty} }"

      if ($session) 
      {
        try 
        {
          
          $DPMDatasources = Invoke-Command -Session $session -ScriptBlock {

            Write-Verbose -Message "Connected via PowerShell remoting as user $($env:username), gathering Data Sources"

            try 
            {
              . ([ScriptBlock]::Create($using:InitializeDPMCXDataSourcePropertyDefinition))

              Import-Module -Name DataProtectionManager -ErrorAction Stop -Verbose:$false

              $VerbosePreference = $Using:VerbosePreference

              $HostName = [System.Net.Dns]::GetHostByName((HOSTNAME.EXE)).HostName

              $DPMServerConnection = Connect-DPMServer -DPMServerName $HostName -WarningAction SilentlyContinue

              $DPMDatasources = Get-DPMDatasource -DPMServerName $HostName -WarningAction SilentlyContinue

              Write-Verbose -Message 'Invoking Initialize-DPMCXDataSourceProperty'
              Initialize-DPMCXDataSourceProperty -DataSource $DPMDatasources

              $DPMDatasources = $DPMDatasources | ForEach-Object -Process {
                $computer = $_.Computer
                $ProductionServerName = $_.ProductionServerName
                $ProtectionGroup = $_.ProtectionGroup
                

                Write-Verbose -Message "Processing Data Source $ProductionServerName"

                #region Schedules

                if ($ProtectionGroup) {

                $Schedules = $ProtectionGroup.GetSchedules()

                if ($Schedules["FullReplicationForApplication"]) {

                $ScheduleInfo = $Schedules["FullReplicationForApplication"]
                Write-Verbose -Message "Protection group $($ProtectionGroup.Name) is using Application schedule"

                } elseif ($Schedules["ShadowCopy"]) {

                $ScheduleInfo = $Schedules["ShadowCopy"]
                Write-Verbose -Message "Protection group $($ProtectionGroup.Name) is using Shadow Copy schedule"

                }

                Write-Verbose -Message "ScheduleDescription: $($ScheduleInfo.ScheduleDescription)"

                if ($ScheduleInfo.ScheduleDescription -notlike "*Everyday*") {

                Write-Verbose -Message "Protection group $($ProtectionGroup.Name) is not backed up every day, calculating latest previous scheduled recovery point time"

                $PreviousWeekDay = $ScheduleInfo.WeekDays[-1]
                $TimesOfDay = $ScheduleInfo.TimesOfDay[-1]

                $DayCounter = 1

                do
                {
                $DayCounter--
                $PreviousRecoveryPoint = (Get-Date -Hour $TimesOfDay.Hour -Minute $TimesOfDay.Minute).AddDays($DayCounter)
                    
                }
                until ($PreviousRecoveryPoint.DayOfWeek -like "$PreviousWeekDay*") 
                
                Write-Verbose -Message "Previous scheduled recovery point time: $PreviousRecoveryPoint"

                $ProtectionGroup | Add-Member -MemberType NoteProperty -Name PreviousRecoveryPoint -Value $PreviousRecoveryPoint -Force

                }

                }
                
                #endregion

                $ProtectedObjects = $_.GetProtectedObjects()

                $LatestRecoveryPoint = $_.LatestRecoveryPoint

                $ProtectedObjects = $_.GetProtectedObjects()

                if ($ProtectedObjects) 
                {
                  $_ | Select-Object -Property Computer, name, objecttype, currentlyprotected, @{
                    n = 'LatestRecoveryPoint'
                    e = {
                      $LatestRecoveryPoint
                    }
                  }, ProductionServerName, ProtectionGroup

                  $ProtectedObjects | Select-Object -Property @{
                    n = 'Computer'
                    e = {
                      $computer
                    }
                  }, @{
                    n = 'name'
                    e = {
                      $_.DisplayPath
                    }
                  }, objecttype, currentlyprotected, @{
                    n = 'LatestRecoveryPoint'
                    e = {
                      $LatestRecoveryPoint
                    }
                  }, @{
                    n = 'ProductionServerName'
                    e = {
                      $ProductionServerName
                    }
                  }, @{
                    n = 'ProtectionGroup'
                    e = {
                      $ProtectionGroup
                    }
                  }
                }
                else 
                {
                  $_ | Select-Object -Property Computer, name, objecttype, currentlyprotected, @{
                    n = 'LatestRecoveryPoint'
                    e = {
                      $LatestRecoveryPoint
                    }
                  }, @{
                    n = 'ProductionServerName'
                    e = {
                      $ProductionServerName
                    }
                  }, @{
                    n = 'ProtectionGroup'
                    e = {
                      $ProtectionGroup
                    }
                  }
                }
              }


              if ($using:OlderThan) 
              {

                Write-Verbose -Message '-OlderThan specified, filtering data sources...'

                $DPMDatasources |
                Where-Object -FilterScript {
                  $_.CurrentlyProtected -and ($_.LatestRecoveryPoint -lt $using:OlderThan)
                } | Foreach-Object -Process {

                  if ($_.ProtectionGroup.PreviousRecoveryPoint) {

                     Write-Verbose -Message "Data source $($_.Name) on protected computer $($_.Computer) has PreviousRecoveryPoint defined, verifying against OlderThan value..."
                     
                     $TimeSpan = New-TimeSpan -Start $using:OlderThan
                     $DesiredMaxAge = $_.ProtectionGroup.PreviousRecoveryPoint.AddDays($TimeSpan.Days)

                     #if ($DesiredMaxAge -lt $_.ProtectionGroup.PreviousRecoveryPoint) {
                    if ($_.LatestRecoveryPoint -gt $DesiredMaxAge) {

                      Write-Verbose -Message "LatestRecoveryPoint $($_.LatestRecoveryPoint) is greater than OlderThan/DesiredMaxAge value $($DesiredMaxAge), adding data source to output..."

                      $_

                     } else {

                      Write-Verbose -Message "LatestRecoveryPoint $($_.LatestRecoveryPoint) is not greater than OlderThan/DesiredMaxAge value $($DesiredMaxAge), data source compliant and not added to output..."

                     }
                     

                  } else {

                    Write-Verbose -Message "Data source $($_.Name) on protected computer $($_.Computer) does not have PreviousRecoveryPoint defined"
                    $_

                  }


                } |
                Select-Object -Property @{
                  n = 'DPMServer'
                  e = {
                    $env:computername
                  }
                }, 
                @{
                  n = 'Connection'
                  e = {
                    'OK'
                  }
                },
                @{
                  n = 'ProtectedComputer'
                  e = {
                    $_.ProductionServerName
                  }
                }, @{
                  n = 'ProtectionGroup'
                  e = {
                    $_.ProtectionGroup.FriendlyName
                  }
                }, @{
                  n = 'DataSource'
                  e = {
                    $_.Name
                  }
                }, LatestRecoveryPoint, @{
                  n = 'Status'
                  e = {
                    "Recovery point older than $using:OlderThan"
                  }
                },
                Errors
              }
              else 
              {
                $DPMDatasources |
                Where-Object -FilterScript {
                  $_.CurrentlyProtected
                } |
                Select-Object -Property @{
                  n = 'DPMServer'
                  e = {
                    $env:computername
                  }
                },
                @{
                  n = 'Connection'
                  e = {
                    'OK'
                  }
                },
                 @{
                  n = 'ProtectedComputer'
                  e = {
                    $_.ProductionServerName
                  }
                }, @{
                  n = 'ProtectionGroup'
                  e = {
                    $_.ProtectionGroup.FriendlyName
                  }
                }, @{
                  n = 'DataSource'
                  e = {
                    $_.Name
                  }
                }, LatestRecoveryPoint, @{
                  n = 'Status'
                  e = {

                  }
                },
                Errors
              }

              Write-Verbose -Message 'Finished processing Data Sources, disconnecting from DPM Server'

              Disconnect-DPMServer
            }

            catch 
            {
              Write-Verbose -Message "An error occured: $($_.Exception.Message)"
          
              throw $_.Exception.Message
          
              break
            }
          } -ErrorAction Stop -Verbose | Select-Object -Property DPMServer, Connection, ProtectedComputer, ProtectionGroup, DataSource, LatestRecoveryPoint, Status, Errors
        }

        catch 
        {
          $DPMDatasources += New-Object -TypeName pscustomobject -Property @{
            'DPMServer'         = $computer
            'Connection'   = 'OK'
            'DataSource'        = $null
            'ProtectedComputer' = $null
            'ProtectionGroup'   = $null
            'LatestRecoveryPoint' = $null
            'Status'            = $null
            'Errors' = "An error occured gathering data: $($_.Exception.Message)"
          }
        }

        Write-Verbose -Message 'Removing PowerShell Remoting session'

        Remove-PSSession -Session $session
      }


      if ($DPMDatasources) 
      {
        $output += $DPMDatasources
      }
      else 
      {
        if ($session) 
        {
          $output += New-Object -TypeName pscustomobject -Property @{
            DPMServer           = $computer
            Connection          = 'OK'
            ProtectedComputer   = $null
            ProtectionGroup     = $null
            DataSource          = $null
            LatestRecoveryPoint = $null
            Status              = "No latest recovery point older than $OlderThan found"
            'Errors' = $null
          }
        }
      }
    }

  }

  end {
  
    return $output

  }
}