Monitoring Exchange 2010 Database Backup and Mount Status

The Exchange 2010 Management Pack for System Center Operations Manager 2007 / 2012 does some of its monitoring remotely rather than on the mailbox server itself. This means that various PowerShell scripts will run on a schedule from the RMS (OM 2007) or the All Management Servers Resource Pool (OM 2012). One of the recommendations in KB2592561 is to disable the database mount status monitor. Several years ago I developed a management pack to monitor whether a database is mounted or not, but in doing this I created a new class that is hosted by the actual database server rather than remotely. This effectively spreads out the load required for this monitoring and also creates a a new class that you can target for other custom monitoring.

Chris Maiden, a Premier Field Engineer out of Washington, DC, recently extended this management pack further by adding a check for LastFullBackup. To test out this management pack in your lab just make sure you already have the latest version of the Exchange 2010 management and import the attached MP.

**Update** (4/21/2014)

One of my peers, Volkan Coskun, found that the discovery script was filtering out valid DBs so I updated the script. We were filtering on Mastertype=server and on HA mailboxes Mastertype is set to databaseAvailabilityGroup. The script has been updated in the attached MP.

Monitors

  • Exchange 2010 Agent Hosted Database Mounted
    • This monitor runs every 5 minutes to determine if the discovered database is mounted or not
  • Exchange 2010 Mailbox Monitoring LastFullBackup Check
    • This monitor runs twice a day. The warning threshold is 7 days while the critical threshold is 14 days.
  • DatabaseHostAvailabilityRollup Dependency Monitor
    • This monitor rolls up health from the custom class to the mail Mailbox Database Service class in the Exchange 2010 MP

Views

  • Exchange 2010 Mailboxes (Agent Hosted)

image

Health Explorer

image

Alerts

image

image

Management Pack

 <ManagementPack ContentReadable="true" xmlns:xsd="https://www.w3.org/2001/XMLSchema">
  <Manifest>
    <Identity>
      <ID>Custom.Example.Exchange.2010.MailboxMonitoring</ID>
      <Version>1.0.0.0</Version>
    </Identity>
    <Name>Exchange 2010 Mailbox Monitoring</Name>
    <References>
      <Reference Alias="MicrosoftExchange2010">
        <ID>Microsoft.Exchange.2010</ID>
        <Version>14.3.38.4</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="SC">
        <ID>Microsoft.SystemCenter.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Windows">
        <ID>Microsoft.Windows.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Health">
        <ID>System.Health.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="System">
        <ID>System.Library</ID>
        <Version>6.1.7221.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
    </References>
  </Manifest>
  <TypeDefinitions>
    <EntityTypes>
      <ClassTypes>
        <ClassType ID="Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService" Accessibility="Public" Abstract="false" Base="MicrosoftExchange2010!Microsoft.Exchange.2010.Component" Hosted="true" Singleton="false">
          <Property ID="DatabaseName" Type="string" Key="true" CaseSensitive="false" MinLength="0" Length="256" />
        </ClassType>
      </ClassTypes>
      <RelationshipTypes>
        <RelationshipType ID="Custom.Example.Exchange.2010.MailboxMonitoring.Relationship.DatabaseServiceContainsDatabase" Accessibility="Public" Abstract="false" Base="System!System.Containment">
          <Source>MicrosoftExchange2010!Microsoft.Exchange.2010.Mailbox.DatabaseService</Source>
          <Target>Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService</Target>
        </RelationshipType>
        <RelationshipType ID="Custom.Example.Exchange.2010.MailboxMonitoring.Relationship.WindowsComputerHostsDatabaseService" Accessibility="Internal" Abstract="false" Base="System!System.Hosting">
          <Source>Windows!Microsoft.Windows.Computer</Source>
          <Target>Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService</Target>
        </RelationshipType>
      </RelationshipTypes>
    </EntityTypes>
    <ModuleTypes>
      <DataSourceModuleType ID="Custom.Example.Exchange.2010.MailboxMonitoring.Datasource" Accessibility="Internal" Batching="false">
        <Configuration>
          <xsd:element minOccurs="1" name="IntervalSeconds" type="xsd:integer" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="TimeoutSeconds" type="xsd:integer" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="Server" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int" />
          <OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int" />
          <OverrideableParameter ID="Server" Selector="$Config/Server$" ParameterType="string" />
        </OverrideableParameters>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <DataSource ID="SS" TypeID="System!System.Scheduler">
                <Scheduler>
                  <SimpleReccuringSchedule>
                    <Interval>$Config/IntervalSeconds$</Interval>
                    <SyncTime />
                  </SimpleReccuringSchedule>
                  <ExcludeDates />
                </Scheduler>
              </DataSource>
              <ProbeAction ID="PS" TypeID="Custom.Example.Exchange.2010.MailboxMonitoring.Probe">
                <TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
                <Server>$Config/Server$</Server>
              </ProbeAction>
            </MemberModules>
            <Composition>
              <Node ID="PS">
                <Node ID="SS" />
              </Node>
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.PropertyBagData</OutputType>
      </DataSourceModuleType>
      <DataSourceModuleType ID="Custom.Example.Exchange.2010.MailboxMonitoring.DS.MountedScriptCookdown" Accessibility="Internal" Batching="false">
        <Configuration>
          <xsd:element minOccurs="1" name="IntervalSeconds" type="xsd:integer" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="TimeoutSeconds" type="xsd:integer" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="MBServer" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="DatabaseName" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int" />
          <OverrideableParameter ID="MBServer" Selector="$Config/MBServer$" ParameterType="string" />
          <OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int" />
        </OverrideableParameters>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <DataSource ID="DS" TypeID="System!System.SimpleScheduler">
                <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
                <SyncTime />
              </DataSource>
              <ProbeAction ID="Probe" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagProbe">
                <ScriptName>MailboxMon2.ps1</ScriptName>
                <ScriptBody>#Get parameters
param($mbxsrv)

#initialize dbcount
$dbcount = 0

#creates the SCOM scripting API
$api = New-Object -comObject MOM.ScriptAPI

#debug event to verify cookdown
# $api.logscriptevent("MailboxMon2.PS1",9898,4,"Verifying cookdown, this event should only happen once per script iteration" )
# $api.logscriptevent("MailboxMon2.PS1",9899,4,$mbxsrv)

#Add Exchange Snap-in for Exchange PowerShell cmdlet support 
Function Load-ExchangeSnapin
{
    if (! (Get-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction:SilentlyContinue) )
    {
        Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
    }
}
Load-ExchangeSnapin

#get database information
$dbs = get-mailboxdatabase -server $mbxsrv -status | select name, server, mounted

#get public folder information
$pfs = get-publicfolderdatabase -server $mbxsrv -status | select name, server, mounted

#debug
$sDBStatus = "`nDatabase Status:`n"
#enddebug

#Loop through databases
foreach($db in $dbs)
{
  #we found a database so increment dbcount
  $dbcount = $dbcount + 1
  
  #debug
  $sDash = " - Mounted = ";
  $sDBStatus = $sDBStatus + $db.Name + $sDash + $db.Mounted + "`n";
  #enddebug
  
  #add information to individual property bags
  $bag = $api.CreatePropertyBag()
  $bag.AddValue('DatabaseName', $db.Name)
  $bag.AddValue('Mounted', $db.Mounted)
  $bag
}

#Loop through public folders
foreach($pf in $pfs)
{
  #we found a database so increment dbcount
  $dbcount = $dbcount + 1
  
  #debug
  $sDash = " - Mounted = ";
  $sDBStatus = $sDBStatus + $pf.Name + $sDash + $pf.Mounted + "`n";
  #enddebug
  
  #add information to individual property bags
  $bag = $api.CreatePropertyBag()
  $bag.AddValue('DatabaseName', $pf.Name)
  $bag.AddValue('Mounted', $pf.Mounted)
  $bag
}

#debug
#Write-Host "Test: MailboxMon2.PS1: " + $sDBStatus
#$api.logscriptevent("MailboxMon1.PS1",9899,4,$sDBStatus)
#enddebug

#Handle auto-activation scenario
if($dbcount -gt 0)
{
  $mbserv = Get-MailboxServer $mbxsrv
  if($mbserv.DatabaseCopyAutoActivationPolicy -eq "Blocked")
  {
    $api.logscriptevent("MailboxMon1.PS1",4369,1,"The Server is hosting active DBs but is auto-activation blocked")
  }
}</ScriptBody>
                <Parameters>
                  <Parameter>
                    <Name>mbxsrv</Name>
                    <Value>$Config/MBServer$</Value>
                  </Parameter>
                </Parameters>
                <TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
              </ProbeAction>
            </MemberModules>
            <Composition>
              <Node ID="Probe">
                <Node ID="DS" />
              </Node>
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.PropertyBagData</OutputType>
      </DataSourceModuleType>
      <ProbeActionModuleType ID="Custom.Example.Exchange.2010.MailboxMonitoring.Probe" Accessibility="Internal" Batching="false" PassThrough="false">
        <Configuration>
          <xsd:element minOccurs="1" name="TimeoutSeconds" type="xsd:integer" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="Server" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int" />
          <OverrideableParameter ID="Server" Selector="$Config/Server$" ParameterType="string" />
        </OverrideableParameters>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <ProbeAction ID="PS" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagProbe">
                <ScriptName>Ex2010LastFullBackup.ps1</ScriptName>
                <ScriptBody>param($Server)

$ScriptName = "Ex2010LastFullBackup.ps1"

Function Load-ExchangeSnapin
{
  if (! (Get-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction:SilentlyContinue) )
  {
    Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
  }
}

Function Create-ErrorEvent ([string]$ScriptName, [string]$EventSeverity, [int]$EventID, [string]$EventDescription) 
{  
  $api = new-object -comObject 'MOM.ScriptAPI'
  $api.LogScriptEvent($ScriptName, $EventID, $EventSeverity, $EventDescription)
}

Load-ExchangeSnapin

$MBdbs = Get-Mailboxdatabase -server $Server -status
$PFdbs = Get-PublicFolderDatabase -server $Server -status 
$Today = Get-Date
$api = new-object -comObject 'MOM.ScriptAPI'

ForEach ($db in $MBdbs)
{
  $DisplayName = $db.AdminDisplayName
  if($db.LastFullBackup -eq $null)
  {
    $Days = 99
  }
  else
  {
    $BckTime = $db.LastFullBackup
    $Delta = $Today - $BckTime
    $Days = $Delta.Days
  }
  $bag = $api.CreatePropertyBag()
  $bag.AddValue('AdminDisplayName', $DisplayName)
  $bag.AddValue('LastFullBackupDays',$Days)
  $bag
  $List += $DisplayName + " " + $Days + "`r`n"
}

ForEach ($db in $PFdbs)
{
  $DisplayName = $db.AdminDisplayName
  if($db.LastFullBackup -eq $null)
  {
    $Days = 99
  }
  else
  {
    $BckTime = $db.LastFullBackup
    $Delta = $Today - $BckTime
    $Days = $Delta.Days
  }
  $bag = $api.CreatePropertyBag()
  $bag.AddValue('AdminDisplayName', $DisplayName)
  $bag.AddValue('LastFullBackupDays',$Days)
  $bag
  $List += $DisplayName + " " + $Days + "`r`n"
}

                </ScriptBody>
                <Parameters>
                  <Parameter>
                    <Name>Server</Name>
                    <Value>$Config/Server$</Value>
                  </Parameter>
                </Parameters>
                <TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
              </ProbeAction>
            </MemberModules>
            <Composition>
              <Node ID="PS" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.PropertyBagData</OutputType>
        <InputType>System!System.BaseData</InputType>
      </ProbeActionModuleType>
    </ModuleTypes>
    <MonitorTypes>
      <UnitMonitorType ID="Custom.Example.Exchange.2010.MailboxMonitoring.AgentHostedDBMountedMonitorType" Accessibility="Internal">
        <MonitorTypeStates>
          <MonitorTypeState ID="Mounted" NoDetection="false" />
          <MonitorTypeState ID="NotMounted" NoDetection="false" />
        </MonitorTypeStates>
        <Configuration>
          <xsd:element minOccurs="1" name="MBServer" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="DatabaseName" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="IntervalSeconds" type="xsd:integer" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="TimeoutSeconds" type="xsd:integer" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int" />
          <OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int" />
        </OverrideableParameters>
        <MonitorImplementation>
          <MemberModules>
            <DataSource ID="DS" TypeID="Custom.Example.Exchange.2010.MailboxMonitoring.DS.MountedScriptCookdown">
              <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
              <TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
              <MBServer>$Config/MBServer$</MBServer>
              <DatabaseName>$Config/DatabaseName$</DatabaseName>
            </DataSource>
            <ConditionDetection ID="CDHealthy" TypeID="System!System.ExpressionFilter">
              <Expression>
                <And>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="String">Property[@Name='DatabaseName']</XPathQuery>
                      </ValueExpression>
                      <Operator>Equal</Operator>
                      <ValueExpression>
                        <Value Type="String">$Config/DatabaseName$</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="String">Property[@Name='Mounted']</XPathQuery>
                      </ValueExpression>
                      <Operator>Equal</Operator>
                      <ValueExpression>
                        <Value Type="String">True</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                </And>
              </Expression>
            </ConditionDetection>
            <ConditionDetection ID="CDNotMounted" TypeID="System!System.ExpressionFilter">
              <Expression>
                <And>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="String">Property[@Name='DatabaseName']</XPathQuery>
                      </ValueExpression>
                      <Operator>Equal</Operator>
                      <ValueExpression>
                        <Value Type="String">$Config/DatabaseName$</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="String">Property[@Name='Mounted']</XPathQuery>
                      </ValueExpression>
                      <Operator>Equal</Operator>
                      <ValueExpression>
                        <Value Type="String">False</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                </And>
              </Expression>
            </ConditionDetection>
          </MemberModules>
          <RegularDetections>
            <RegularDetection MonitorTypeStateID="Mounted">
              <Node ID="CDHealthy">
                <Node ID="DS" />
              </Node>
            </RegularDetection>
            <RegularDetection MonitorTypeStateID="NotMounted">
              <Node ID="CDNotMounted">
                <Node ID="DS" />
              </Node>
            </RegularDetection>
          </RegularDetections>
        </MonitorImplementation>
      </UnitMonitorType>
      <UnitMonitorType ID="Custom.Example.Exchange.2010.MailboxMonitoring.LastFullBackupMonitorType" Accessibility="Internal">
        <MonitorTypeStates>
          <MonitorTypeState ID="Healthy" NoDetection="false" />
          <MonitorTypeState ID="Warning" NoDetection="false" />
          <MonitorTypeState ID="Critical" NoDetection="false" />
        </MonitorTypeStates>
        <Configuration>
          <xsd:element minOccurs="1" name="IntervalSeconds" type="xsd:integer" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="TimeoutSeconds" type="xsd:integer" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="Server" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="WarningThresholdDays" type="xsd:integer" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="CriticalThresholdDays" type="xsd:integer" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="DatabaseName" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int" />
          <OverrideableParameter ID="TimeoutSeconds" Selector="$Config/TimeoutSeconds$" ParameterType="int" />
          <OverrideableParameter ID="WarningThresholdDays" Selector="$Config/WarningThresholdDays$" ParameterType="int" />
          <OverrideableParameter ID="CriticalThresholdDays" Selector="$Config/CriticalThresholdDays$" ParameterType="int" />
        </OverrideableParameters>
        <MonitorImplementation>
          <MemberModules>
            <DataSource ID="DS" TypeID="Custom.Example.Exchange.2010.MailboxMonitoring.Datasource">
              <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
              <TimeoutSeconds>$Config/TimeoutSeconds$</TimeoutSeconds>
              <Server>$Config/Server$</Server>
            </DataSource>
            <ConditionDetection ID="HealthyCD" TypeID="System!System.ExpressionFilter">
              <Expression>
                <And>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="String">Property[@Name='AdminDisplayName']</XPathQuery>
                      </ValueExpression>
                      <Operator>Equal</Operator>
                      <ValueExpression>
                        <Value Type="String">$Config/DatabaseName$</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="Double">Property[@Name='LastFullBackupDays']</XPathQuery>
                      </ValueExpression>
                      <Operator>Less</Operator>
                      <ValueExpression>
                        <Value Type="Double">$Config/WarningThresholdDays$</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                </And>
              </Expression>
            </ConditionDetection>
            <ConditionDetection ID="WarningCD" TypeID="System!System.ExpressionFilter">
              <Expression>
                <And>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="String">Property[@Name='AdminDisplayName']</XPathQuery>
                      </ValueExpression>
                      <Operator>Equal</Operator>
                      <ValueExpression>
                        <Value Type="String">$Config/DatabaseName$</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="Double">Property[@Name='LastFullBackupDays']</XPathQuery>
                      </ValueExpression>
                      <Operator>GreaterEqual</Operator>
                      <ValueExpression>
                        <Value Type="Double">$Config/WarningThresholdDays$</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="Double">Property[@Name='LastFullBackupDays']</XPathQuery>
                      </ValueExpression>
                      <Operator>Less</Operator>
                      <ValueExpression>
                        <Value Type="Double">$Config/CriticalThresholdDays$</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                </And>
              </Expression>
            </ConditionDetection>
            <ConditionDetection ID="CriticalCD" TypeID="System!System.ExpressionFilter">
              <Expression>
                <And>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="String">Property[@Name='AdminDisplayName']</XPathQuery>
                      </ValueExpression>
                      <Operator>Equal</Operator>
                      <ValueExpression>
                        <Value Type="String">$Config/DatabaseName$</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                  <Expression>
                    <SimpleExpression>
                      <ValueExpression>
                        <XPathQuery Type="Double">Property[@Name='LastFullBackupDays']</XPathQuery>
                      </ValueExpression>
                      <Operator>GreaterEqual</Operator>
                      <ValueExpression>
                        <Value Type="Double">$Config/CriticalThresholdDays$</Value>
                      </ValueExpression>
                    </SimpleExpression>
                  </Expression>
                </And>
              </Expression>
            </ConditionDetection>
          </MemberModules>
          <RegularDetections>
            <RegularDetection MonitorTypeStateID="Healthy">
              <Node ID="HealthyCD">
                <Node ID="DS" />
              </Node>
            </RegularDetection>
            <RegularDetection MonitorTypeStateID="Warning">
              <Node ID="WarningCD">
                <Node ID="DS" />
              </Node>
            </RegularDetection>
            <RegularDetection MonitorTypeStateID="Critical">
              <Node ID="CriticalCD">
                <Node ID="DS" />
              </Node>
            </RegularDetection>
          </RegularDetections>
        </MonitorImplementation>
      </UnitMonitorType>
    </MonitorTypes>
  </TypeDefinitions>
  <Monitoring>
    <Discoveries>
      <Discovery ID="Custom.Example.Exchange.2010.MailboxMonitoring.Discovery.DiscoverAgentHostedDBs" Enabled="true" Target="MicrosoftExchange2010!Microsoft.Exchange.2010.Mailbox.MailboxMonitoring" ConfirmDelivery="true" Remotable="true" Priority="Normal">
        <Category>Discovery</Category>
        <DiscoveryTypes>
          <DiscoveryClass TypeID="Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService" />
        </DiscoveryTypes>
        <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.TimedPowerShell.DiscoveryProvider">
          <IntervalSeconds>43200</IntervalSeconds>
          <SyncTime />
          <ScriptName>DiscoverDBs.ps1</ScriptName>
          <ScriptBody>#Set variables
$computerPrincipalName = "$Target/Host/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$"
$computerNetbiosName = "$Target/Host/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/NetbiosComputerName$"
$sourceId = "$MPElement$"
$managedEntityId = "$Target/Id$"
$componentNameProperty = "$MPElement[Name='MicrosoftExchange2010!Microsoft.Exchange.2010.Component']/ComponentName$"
$instanceNameProperty = "$MPElement[Name='MicrosoftExchange2010!Microsoft.Exchange.2010.Component']/InstanceName$"
$displayNameProperty = "$MPElement[Name='System!System.Entity']/DisplayName$"
$principalNameProperty = "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$"
$componentName = "Mounted Database (Hosted by Agent)"
$dnsDomainNameProperty = "$Target/Host/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/ForestDnsName$"

#$api.logscriptevent("DiscoverDBs.ps1",9898,4,"Start DiscoverDBs.ps1.")

#creates the SCOM scripting API
$api = New-Object -comObject MOM.ScriptAPI

#Create Discovery Data
$discoveryData = $api.CreateDiscoveryData(0, $sourceId, $managedEntityId)

#Add Exchange Snap-in for Exchange PowerShell cmdlet support 
Function Load-ExchangeSnapin
{
    if (! (Get-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction:SilentlyContinue) )
    {
        Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
    }
}
Load-ExchangeSnapin

#Get databases on local server that are currently mounted 
$mailboxDBs = @(Get-MailboxDatabase -Server $computerPrincipalName -Status | where {($_.recovery -eq $false)})

#Get public folders on local server that are currently mounted
$publicFolderDBs = @(Get-PublicFolderDatabase -Server $computerPrincipalName -Status | where {($_.recovery -eq $false)})

#debug
$sDiscoveredItems = "`nDiscovered Databases:`n"
#enddebug

#Loop through each database
$mailboxDBs | foreach {

  #We discovered a database, now create an instance
  $db = $discoveryData.CreateClassInstance("$MPElement[Name='Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService']$");
  
  #Populate the properties of the class and key properties of hosting classes
  $db.AddProperty($componentNameProperty, $componentName);
  $db.AddProperty($instanceNameProperty, $_.Name);
  $db.AddProperty($displayNameProperty, $_.Name);
  $db.AddProperty($principalNameProperty, $computerPrincipalName);
  $db.AddProperty("$MPElement[Name='Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService']/DatabaseName$", $_.Name);
  
  #Add instance back to workflow
  $discoveryData.AddInstance($db);
  
  #Create an instance of the DatabaseService class so we can link the two with a relationship
  $dbName = $_.Name
  $dbService = $discoveryData.CreateClassInstance("$MPElement[Name='MicrosoftExchange2010!Microsoft.Exchange.2010.Mailbox.DatabaseService']$");
  $dbService.AddProperty("$MPElement[Name='MicrosoftExchange2010!Microsoft.Exchange.2010.Service']/ServiceName$", "Mailbox Database Service - $dbName - $dnsDomainNameProperty");
  
  #Add instance back to workflow
  $discoveryData.AddInstance($dbService);
  
  #Create a relationship between this instance and the instance of DatabaseService
  $dbRel = $discoveryData.CreateRelationshipInstance("$MPElement[Name='Custom.Example.Exchange.2010.MailboxMonitoring.Relationship.DatabaseServiceContainsDatabase']$");
  $dbRel.Source = $dbService;
  $dbRel.Target = $db;
  
  #debug
  $sDiscoveredItems = $sDiscoveredItems + $dbName + "`n";
  #enddebug
  
  #Add instance back to workflow
  $discoveryData.AddInstance($dbRel);
}

#Loop through each public folder
$publicFolderDBs | foreach {
  #We discovered a database, now create an instance
  $db = $discoveryData.CreateClassInstance("$MPElement[Name='Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService']$");
  
  #Populate the properties of the class and key properties of hosting classes
  $db.AddProperty($componentNameProperty, $componentName);
  $db.AddProperty($instanceNameProperty, $_.Name);
  $db.AddProperty($displayNameProperty, $_.Name);
  $db.AddProperty($principalNameProperty, $computerPrincipalName);
  $db.AddProperty("$MPElement[Name='Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService']/DatabaseName$", $_.Name);
  
  #Add instance back to workflow
  $discoveryData.AddInstance($db);
  
  #Create an instance of the DatabaseService class so we can link the two with a relationship
  $dbName = $_.Name
  $dbService = $discoveryData.CreateClassInstance("$MPElement[Name='MicrosoftExchange2010!Microsoft.Exchange.2010.Mailbox.DatabaseService']$");
  $dbService.AddProperty("$MPElement[Name='MicrosoftExchange2010!Microsoft.Exchange.2010.Service']/ServiceName$", "Mailbox Database Service - $dbName - $dnsDomainNameProperty");
  
  #Add instance back to workflow
  $discoveryData.AddInstance($dbService);
  
  #Create a relationship between this instance and the instance of DatabaseService
  $dbRel = $discoveryData.CreateRelationshipInstance("$MPElement[Name='Custom.Example.Exchange.2010.MailboxMonitoring.Relationship.DatabaseServiceContainsDatabase']$");
  $dbRel.Source = $dbService;
  $dbRel.Target = $db;
  
  #debug
  $sDiscoveredItems = $sDiscoveredItems + $dbName + "`n";
  #enddebug
  
  #Add instance back to workflow
  $discoveryData.AddInstance($dbRel);
}

#debug
Write-Host $sDiscoveredItems
#$api.logscriptevent("DiscoverDBs.ps1",9898,4,$sDiscoveredItems)
#enddebug

#Return all instances back to OpsMgr agent 
$discoveryData</ScriptBody>
          <TimeoutSeconds>300</TimeoutSeconds>
        </DataSource>
      </Discovery>
    </Discoveries>
    <Monitors>
      <UnitMonitor ID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitor.LastFullBackup" Accessibility="Public" Enabled="true" Target="Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" TypeID="Custom.Example.Exchange.2010.MailboxMonitoring.LastFullBackupMonitorType" ConfirmDelivery="true">
        <Category>AvailabilityHealth</Category>
        <AlertSettings AlertMessage="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitor.LastFullBackup_AlertMessageResourceID">
          <AlertOnState>Warning</AlertOnState>
          <AutoResolve>true</AutoResolve>
          <AlertPriority>Normal</AlertPriority>
          <AlertSeverity>MatchMonitorHealth</AlertSeverity>
          <AlertParameters>
            <AlertParameter1>$Data/Context/Property[@Name='LastFullBackupDays']$</AlertParameter1>
          </AlertParameters>
        </AlertSettings>
        <OperationalStates>
          <OperationalState ID="UIGeneratedOpStateId5a42f14119624ef49578c932c0fe1ede" MonitorTypeStateID="Healthy" HealthState="Success" />
          <OperationalState ID="UIGeneratedOpStateId8da552b98a8b441ab38e79eed3f8eb2d" MonitorTypeStateID="Warning" HealthState="Warning" />
          <OperationalState ID="UIGeneratedOpStateIdf3e7f44b20f040c68b0afbb3b0c1af92" MonitorTypeStateID="Critical" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <IntervalSeconds>43200</IntervalSeconds>
          <TimeoutSeconds>120</TimeoutSeconds>
          <Server>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Server>
          <WarningThresholdDays>7</WarningThresholdDays>
          <CriticalThresholdDays>14</CriticalThresholdDays>
          <DatabaseName>$Target/Property[Type="Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService"]/DatabaseName$</DatabaseName>
        </Configuration>
      </UnitMonitor>
      <UnitMonitor ID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitorAgentHostedDBMounted" Accessibility="Internal" Enabled="true" Target="Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" TypeID="Custom.Example.Exchange.2010.MailboxMonitoring.AgentHostedDBMountedMonitorType" ConfirmDelivery="true">
        <Category>AvailabilityHealth</Category>
        <AlertSettings AlertMessage="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitorAgentHostedDBMounted_AlertMessageResourceID">
          <AlertOnState>Error</AlertOnState>
          <AutoResolve>true</AutoResolve>
          <AlertPriority>Normal</AlertPriority>
          <AlertSeverity>Error</AlertSeverity>
        </AlertSettings>
        <OperationalStates>
          <OperationalState ID="UIGeneratedOpStateIde67ab2dce42745a89e573c8e2b679418" MonitorTypeStateID="Mounted" HealthState="Success" />
          <OperationalState ID="UIGeneratedOpStateId46a3b584a8784c889da530083480f301" MonitorTypeStateID="NotMounted" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <MBServer>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</MBServer>
          <DatabaseName>$Target/Property[Type="Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService"]/DatabaseName$</DatabaseName>
          <IntervalSeconds>300</IntervalSeconds>
          <TimeoutSeconds>240</TimeoutSeconds>
        </Configuration>
      </UnitMonitor>
      <DependencyMonitor ID="Custom.Example.Exchange.2010.MailboxMonitoring.Monitor.DatabaseHostAvailabilityRollup" Accessibility="Public" Enabled="true" Target="MicrosoftExchange2010!Microsoft.Exchange.2010.Mailbox.DatabaseService" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" RelationshipType="Custom.Example.Exchange.2010.MailboxMonitoring.Relationship.DatabaseServiceContainsDatabase" MemberMonitor="Health!System.Health.AvailabilityState">
        <Category>AvailabilityHealth</Category>
        <Algorithm>WorstOf</Algorithm>
      </DependencyMonitor>
    </Monitors>
  </Monitoring>
  <Presentation>
    <Views>
      <View ID="Custom.Example.Exchange.2010.MailboxMonitoring.AgentMailboxView" Accessibility="Internal" Enabled="true" Target="Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService" TypeID="SC!Microsoft.SystemCenter.StateViewType" Visible="true">
        <Category>StateCollection</Category>
        <Criteria />
      </View>
    </Views>
    <FolderItems>
      <FolderItem ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.AgentMailboxView" Folder="MicrosoftExchange2010!Microsoft.Exchange.2010.Mailbox.Folder" />
    </FolderItems>
    <StringResources>
      <StringResource ID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitor.LastFullBackup_AlertMessageResourceID" />
      <StringResource ID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitorAgentHostedDBMounted_AlertMessageResourceID" />
    </StringResources>
  </Presentation>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.Datasource">
          <Name>Exchange 2010 LastFullBackup Datasource</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.AgentHostedDBMountedMonitorType">
          <Name>Exchange 2010 Agent Hosted DB Mounted MonitorType</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.DS.MountedScriptCookdown">
          <Name>Mounted Script Cookdown</Name>
          <Description>Checks the state of the DBs and returns a separate property bag per DB.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.LastFullBackupMonitorType">
          <Name>Exchange 2010 Mailbox Monitoring LastFullBackup Monitor Type</Name>
          <Description />
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.Probe">
          <Name>Exchange 2010 LastFullBackup Probe</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.Discovery.DiscoverAgentHostedDBs">
          <Name>Agent Hosted Mounted Database Discovery</Name>
          <Description>This discovery should discover the same instances as the DatabaseService class but it is hosted by the agent rather than the RMS or RMS Emulator.  The discovery script runs by default once an hour, which is outside of the recommended frequency for a discovery.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService">
          <Name>Mailbox Database Mounted (Agent Hosted)</Name>
          <Description>This class should contain the same instances as the Microsoft.Exchange.2010.Mailbox.DatabaseService class except it is hosted by the Exchange Server rather than the RMS or RMS Emulator.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.Class.Mailbox.HostedDatabaseService" SubElementID="DatabaseName">
          <Name>Database Name</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.Relationship.DatabaseServiceContainsDatabase">
          <Name>Database Service Contains Agent Hosted Database Relationship</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.Relationship.WindowsComputerHostsDatabaseService">
          <Name>Windows Computer Hosts Database Service Relationship</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring">
          <Name>Exchange 2010 Mailbox Monitoring</Name>
          <Description>Custom Exchange Monitoring</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitor.LastFullBackup">
          <Name>Exchange 2010 Mailbox Monitoring LastFullBackup Check</Name>
          <Description>This monitor checks the LastFullBackup property of the Agent Hosted Mailbox to dtermine how long since the last backup.  The monitor will change states based on the configured thresholds.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitor.LastFullBackup" SubElementID="UIGeneratedOpStateId5a42f14119624ef49578c932c0fe1ede">
          <Name>Healthy</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitor.LastFullBackup" SubElementID="UIGeneratedOpStateId8da552b98a8b441ab38e79eed3f8eb2d">
          <Name>Warning</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitor.LastFullBackup" SubElementID="UIGeneratedOpStateIdf3e7f44b20f040c68b0afbb3b0c1af92">
          <Name>Critical</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitor.LastFullBackup_AlertMessageResourceID">
          <Name>Exchange 2010 Mailbox Monitoring LastFullBackup Check</Name>
          <Description>The database has not been backed up for at least {0} days. </Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitorAgentHostedDBMounted">
          <Name>Exchange 2010 Agent Hosted Database Mounted</Name>
          <Description>This monitor determines if the agent hosted database is either mounted or dismounted.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitorAgentHostedDBMounted" SubElementID="UIGeneratedOpStateId46a3b584a8784c889da530083480f301">
          <Name>NotMounted</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitorAgentHostedDBMounted" SubElementID="UIGeneratedOpStateIde67ab2dce42745a89e573c8e2b679418">
          <Name>Mounted</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.UnitMonitorAgentHostedDBMounted_AlertMessageResourceID">
          <Name>Exchange 2010 Agent Hosted Database is Not Mounted</Name>
          <Description>Exchange 2010 Agent Hosted database is not mounted.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.Exchange.2010.MailboxMonitoring.AgentMailboxView">
          <Name>Exchange 2010 Mailboxes (Agent Hosted)</Name>
        </DisplayString>
      </DisplayStrings>
      <KnowledgeArticles></KnowledgeArticles>
    </LanguagePack>
  </LanguagePacks>
</ManagementPack>

Custom.Example.Exchange.2010.MailboxMonitoring.renametoxml