Monitoring Point-of-Sale Devices Remotely Using System Center Operations Manager

Back in 2010 I developed a management pack to monitor retail point of sale devices. The design takes on an architecture similar to our Cross Platform monitoring solution in that a watcher reaches out to the device and pulls monitoring data at an interval and then the watcher evaluates the data retrieved. This model could be used for monitoring any accessible devices remotely, not just cash registers.

 

image

Design

We considered putting full OM agents on each device but this would have required a significant number of management groups since the supported agent limit per management group was 10,000 (it’s 15,000 in 2012). Also, a full agent wasn’t really necessary since we only wanted to monitor a few key health indicators on each device. The design, however, does allow for full agents to be part of the distributed application if they happen to exist within the store. The out of the box agentless monitoring wouldn’t have scaled well in this scenario for multiple reasons, mainly that we wanted to monitor the devices from within the store and couldn’t put management servers at each store.

The biggest advantage to this design is that the agentless registers are not actual agents in OM so they don’t count against the agent limit per management group. The only scale issues to consider with this solution are with the watcher itself (how many devices can it monitor at one time), the instance space (how many instances are we discovering), and the performance collection (how much more data are we collecting as we scale out).

Discovery

Discovering the Stores, Watchers, and Registers was quite elegant in my original management pack as it used LDAP queries and a seed class to accomplish this based on naming conventions. To demonstrate this solution I had to make it something much more simple so I’m using registry entries. In a production scenario this could be changed to use some other data source along with seed classes in order to utilize a more efficient and dynamic discovery method.

Monitoring

The register watcher, which runs the actual OM agent on a machine within the store, is utilizing WMI to access the remote devices in order to get the data necessary to establish health. It also hosts the Agentless Register class so that each register has health associated with it. Each monitor has an associated performance collection rule and they two cook down as long as they are set to the same schedule. For each metric we stagger the schedule to lower the impact on the watcher. For instance, if the watcher is monitoring 60 devices it will only reach out to 60 at one time so long as the schedules for each metric are staggered.

image

Steps to Test

Configure the Register Watchers

  • Pick several OM agents in your lab to be register watchers
  • Enable Act as Proxy on the Watchers
  • Modify the registry on each watcher entering the store code for the store and a list of registers you want to monitor. In my test case I just used real machines that I could access WMI on.
    • Create a new key: HKLM\Software\Retail
      • Create a string value called “Store” and enter a store code which will be unique for that store
      • Create a multi string value called “Registers” and populate it with a list of machines that will act as registers

image

Configure the MP

  • Import the management pack
  • Add an account that has access to the “registers” to the “Agentless Device Monitoring RunAs Profile”. This account is necessary to be able to remotely access the devices.

View the results

Distributed Application

image

Health Explorer for an Agentless Register

image

Management Pack

 <?xml version="1.0" encoding="utf-8"?>
<ManagementPack SchemaVersion="2.0" ContentReadable="true" xmlns:xsd="https://www.w3.org/2001/XMLSchema">
  <Manifest>
    <Identity>
      <ID>Custom.Example.AgentlessDeviceMonitoring</ID>
      <Version>1.0.0.0</Version>
    </Identity>
    <Name>Agentless Device Monitoring</Name>
    <References>
      <Reference Alias="SCDW">
        <ID>Microsoft.SystemCenter.DataWarehouse.Library</ID>
        <Version>7.1.10226.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="SC">
        <ID>Microsoft.SystemCenter.Library</ID>
        <Version>7.0.8433.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Windows">
        <ID>Microsoft.Windows.Library</ID>
        <Version>7.5.8501.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="Health">
        <ID>System.Health.Library</ID>
        <Version>7.0.8433.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
      <Reference Alias="System">
        <ID>System.Library</ID>
        <Version>7.5.8501.0</Version>
        <PublicKeyToken>31bf3856ad364e35</PublicKeyToken>
      </Reference>
    </References>
  </Manifest>
  <TypeDefinitions>
    <EntityTypes>
      <ClassTypes>
        <ClassType ID="Custom.Example.AgentlessDeviceMonitoring.Class.Retail" Accessibility="Internal" Abstract="false" Base="System!System.Service" Hosted="false" Singleton="true" Extension="false" />
        <ClassType ID="Custom.Example.AgentlessDeviceMonitoring.Class.Store" Accessibility="Internal" Abstract="false" Base="System!System.ApplicationComponent" Hosted="false" Singleton="false" Extension="false">
          <Property ID="StoreCode" Type="string" AutoIncrement="false" Key="true" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />
        </ClassType>
        <ClassType ID="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" Accessibility="Public" Abstract="false" Base="System!System.Perspective" Hosted="true" Singleton="false" Extension="false">
          <Property ID="StoreCode" Type="string" AutoIncrement="false" Key="true" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />
          <Property ID="RegisterName" Type="string" AutoIncrement="false" Key="true" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />
        </ClassType>
        <ClassType ID="Custom.Example.AgentlessDeviceMonitoring.Class.Store.Register" Accessibility="Public" Abstract="false" Base="Windows!Microsoft.Windows.ComputerRole" Hosted="true" Singleton="false" Extension="false">
          <Property ID="StoreCode" Type="string" AutoIncrement="false" Key="true" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />
        </ClassType>
        <ClassType ID="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher" Accessibility="Public" Abstract="false" Base="Windows!Microsoft.Windows.ComputerRole" Hosted="true" Singleton="false" Extension="false">
          <Property ID="StoreCode" Type="string" AutoIncrement="false" Key="true" CaseSensitive="false" MaxLength="256" MinLength="0" Required="false" Scale="0" />
        </ClassType>
        <ClassType ID="Custom.Example.AgentlessDeviceMonitoring.Class.Stores" Accessibility="Internal" Abstract="false" Base="System!System.ApplicationComponent" Hosted="false" Singleton="true" Extension="false" />
      </ClassTypes>
      <RelationshipTypes>
        <RelationshipType ID="Custom.Example.AgentlessDeviceMonitoring.Relationship.RegisterWatcherHostsAgentlessRegister" Accessibility="Internal" Abstract="false" Base="System!System.Hosting">
          <Source ID="Source" MinCardinality="0" MaxCardinality="2147483647" Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher" />
          <Target ID="Target" MinCardinality="0" MaxCardinality="2147483647" Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" />
        </RelationshipType>
        <RelationshipType ID="Custom.Example.AgentlessDeviceMonitoring.Relationship.RetailContainsStores" Accessibility="Internal" Abstract="false" Base="System!System.Containment">
          <Source ID="Source" MinCardinality="0" MaxCardinality="2147483647" Type="Custom.Example.AgentlessDeviceMonitoring.Class.Retail" />
          <Target ID="Target" MinCardinality="0" MaxCardinality="2147483647" Type="Custom.Example.AgentlessDeviceMonitoring.Class.Stores" />
        </RelationshipType>
        <RelationshipType ID="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsAgentlessStoreRegister" Accessibility="Internal" Abstract="false" Base="System!System.Containment">
          <Source ID="Source" MinCardinality="0" MaxCardinality="2147483647" Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store" />
          <Target ID="Target" MinCardinality="0" MaxCardinality="2147483647" Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" />
        </RelationshipType>
        <RelationshipType ID="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsStoreRegister" Accessibility="Internal" Abstract="false" Base="System!System.Containment">
          <Source ID="Source" MinCardinality="0" MaxCardinality="2147483647" Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store" />
          <Target ID="Target" MinCardinality="0" MaxCardinality="2147483647" Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store.Register" />
        </RelationshipType>
        <RelationshipType ID="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsStoreRegisterWatcher" Accessibility="Internal" Abstract="false" Base="System!System.Containment">
          <Source ID="Source" MinCardinality="0" MaxCardinality="2147483647" Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store" />
          <Target ID="Target" MinCardinality="0" MaxCardinality="2147483647" Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher" />
        </RelationshipType>
        <RelationshipType ID="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoresContainsStore" Accessibility="Internal" Abstract="false" Base="System!System.Containment">
          <Source ID="Source" MinCardinality="0" MaxCardinality="2147483647" Type="Custom.Example.AgentlessDeviceMonitoring.Class.Stores" />
          <Target ID="Target" MinCardinality="0" MaxCardinality="2147483647" Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store" />
        </RelationshipType>
      </RelationshipTypes>
    </EntityTypes>
    <SecureReferences>
      <SecureReference ID="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" Accessibility="Internal" />
    </SecureReferences>
    <ModuleTypes>
      <DataSourceModuleType ID="Custom.Example.AgentlessDeviceMonitoring.DataSource.DiscoverDevices" 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="RegisterOrAgentlessRegisterOrRegisterWatcher" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="StoreCode" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="HostName" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int" />
          <OverrideableParameter ID="RegisterOrAgentlessRegisterOrRegisterWatcher" Selector="$Config/RegisterOrAgentlessRegisterOrRegisterWatcher$" ParameterType="string" />
          <OverrideableParameter ID="StoreCode" Selector="$Config/StoreCode$" ParameterType="string" />
        </OverrideableParameters>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.TimedPowerShell.DiscoveryProvider">
                <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
                <SyncTime />
                <ScriptName>DiscoverDevices.ps1</ScriptName>
                <ScriptBody><![CDATA[param ($sSourceId,$sManagedEntityId,$sDiscoveryType,$sStoreCode,$sHostName)
$oAPI = New-Object -comObject 'MOM.ScriptAPI'
$oDiscoveryData = $oAPI.CreateDiscoveryData(0, $sSourceId, $sManagedEntityId)

#Get Registers
$key = Get-ItemProperty 'hklm:\SOFTWARE\Retail'
$colResults = $key.Registers

#Figure out which class we need to discover instances for
if ($sDiscoveryType -eq "Register")
{
  $oInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store.Register']$")
  $oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $sFQDN)
  $oInstance.AddProperty("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store.Register']/StoreCode$", $sStoreCode)
  $oDiscoveryData.AddInstance($oInstance)
}
elseif ($sDiscoveryType -eq "AgentlessRegister")
{
  foreach ($oResult in $colResults)
  {
    $sFQDN = $oResult.ToString()
    $oInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister']$")
    $oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $sHostName)
    $oInstance.AddProperty("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher']/StoreCode$", $sStoreCode)
    $oInstance.AddProperty("$MPElement[Name='System!System.Entity']/DisplayName$", $sFQDN)
    $oInstance.AddProperty("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister']/StoreCode$", $sStoreCode)
    $oInstance.AddProperty("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister']/RegisterName$", $sFQDN)
    $oDiscoveryData.AddInstance($oInstance)
  }
}
elseif ($sDiscoveryType -eq "RegisterWatcher")
{
  $oInstance = $oDiscoveryData.CreateClassInstance("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher']$")
  $oInstance.AddProperty("$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", $sFQDN)
  $oInstance.AddProperty("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher']/StoreCode$", $sStoreCode)
  $oDiscoveryData.AddInstance($oInstance)
}

$oDiscoveryData]]></ScriptBody>
                <Parameters>
                  <Parameter>
                    <Name>sSourceID</Name>
                    <Value>$MPElement$</Value>
                  </Parameter>
                  <Parameter>
                    <Name>sManagedEntityID</Name>
                    <Value>$Target/Id$</Value>
                  </Parameter>
                  <Parameter>
                    <Name>sDiscoveryType</Name>
                    <Value>$Config/RegisterOrAgentlessRegisterOrRegisterWatcher$</Value>
                  </Parameter>
                  <Parameter>
                    <Name>sStoreCode</Name>
                    <Value>$Config/StoreCode$</Value>
                  </Parameter>
                  <Parameter>
                    <Name>sHostName</Name>
                    <Value>$Config/HostName$</Value>
                  </Parameter>
                </Parameters>
                <TimeoutSeconds>300</TimeoutSeconds>
              </DataSource>
            </MemberModules>
            <Composition>
              <Node ID="DS" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.Discovery.Data</OutputType>
      </DataSourceModuleType>
      <DataSourceModuleType ID="Custom.Example.AgentlessDeviceMonitoring.DataSource.DiscoverStore" 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="ComputerName" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="StoreCode" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="ServerOrClient" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int" />
        </OverrideableParameters>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.TimedScript.DiscoveryProvider">
                <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
                <SyncTime />
                <ScriptName>DiscoverStoreRelationships.vbs</ScriptName>
                <Arguments>$MPElement$ $Target/Id$ $Config/ComputerName$ $Config/StoreCode$ $Config/ServerOrClient$</Arguments>
                <ScriptBody><![CDATA[SetLocale("en-us")
On Error Resume Next

Dim SourceId : SourceId = WScript.Arguments(0)                 'GUID of discovery calling the script.  Provided by the MPElement variable.
Dim ManagedEntityId : ManagedEntityId = WScript.Arguments(1)            'GUID of target object.  Provided by the Target/Id variable.
Dim sComputerName : sComputerName = WScript.Arguments(2)            'Name of the computer holding the Store Server or Store Client class.
Dim sStoreCode : sStoreCode = WScript.Arguments(3)                'StoreCode of the Store to create.  Taken from the registry of the target computer.
Dim sServerOrClient : sServerOrClient = LCase(WScript.Arguments(4))    'String of "server" or "client" depending on which type of class is calling script.

Dim oAPI : Set oAPI = CreateObject("MOM.ScriptAPI")
Dim oDiscoveryData : Set oDiscoveryData = oAPI.CreateDiscoveryData(0, SourceId, ManagedEntityId)
Dim oStoreInstance : Set oStoreInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store']$")
oStoreInstance.AddProperty "$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store']/StoreCode$", sStoreCode
oDiscoveryData.AddInstance(oStoreInstance)

'Create an instance of the appropriate classes depending on whether a Store Server or Store Client is calling the script.
If sServerOrClient = "server" Then
    'Create a class instance of Store Server and a Relationship Instance of Store Contains Store Server.
    Set oComputerInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher']$")
    oComputerInstance.AddProperty "$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher']/StoreCode$", sStoreCode
    Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsStoreRegisterWatcher']$")    
Else
    'Create a class instance of Store Client and a Relationship Instance of Store Contains Store Client.
    Set oComputerInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store.Register']$")
    oComputerInstance.AddProperty "$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Class.Store.Register']/StoreCode$", sStoreCode    
    Set oRelationshipInstance = oDiscoveryData.CreateRelationshipInstance("$MPElement[Name='Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsStoreRegister']$")    
End If

'Provide the PrincipalName property for the computer instance created above and add to the discovery data.
'This is required because both the Store Server and Store Client classes are based on Windows ComputerRole.
'    Windows ComputerRole is hosted by Windows Computer.
'    When creating a new instance of a class, we need to provide the key properties of that class and any hosting classes.
oComputerInstance.AddProperty "$MPElement[Name='Windows!Microsoft.Windows.Computer']/PrincipalName$", sComputerName
oDiscoveryData.AddInstance(oComputerInstance)

'With the instance of Store and either Store Server or Store Client created, we can set the Source and Target of the relationship.
oRelationshipInstance.Source = oStoreInstance
oRelationshipInstance.Target = oComputerInstance
oDiscoveryData.AddInstance(oRelationshipInstance)

'Return the discovery data.
oAPI.Return(oDiscoveryData)]]></ScriptBody>
                <TimeoutSeconds>300</TimeoutSeconds>
              </DataSource>
            </MemberModules>
            <Composition>
              <Node ID="DS" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.Discovery.Data</OutputType>
      </DataSourceModuleType>
      <DataSourceModuleType ID="Custom.Example.AgentlessDeviceMonitoring.DataSource.WMIHealthCheck" 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="Arguments" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="SyncTime" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="string" />
          <OverrideableParameter ID="Arguments" Selector="$Config/Arguments$" ParameterType="string" />
          <OverrideableParameter ID="SyncTime" Selector="$Config/SyncTime$" ParameterType="string" />
        </OverrideableParameters>
        <ModuleImplementation Isolation="Any">
          <Composite>
            <MemberModules>
              <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.TimedScript.PropertyBagProvider">
                <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
                <SyncTime>$Config/SyncTime$</SyncTime>
                <ScriptName>WMIHealthCheck.vbs</ScriptName>
                <Arguments>$Config/Arguments$</Arguments>
                <ScriptBody><![CDATA[SetLocale("en-us")
Wscript.Echo "Starting Script"
Dim bLocal : bLocal = WScript.Arguments(0)

'Create property bag
Wscript.Echo "Creating Property Bag"
Dim oAPI : Set oAPI = CreateObject("MOM.ScriptAPI")
Dim oBag : Set oBag = oAPI.CreatePropertyBag()

'Create WMI Connection object
WScript.Echo "Creating WMI Locator"
Dim oWMILocator : Set oWMILocator = CreateObject("WbemScripting.SWbemLocator")

'Connect to WMI
WScript.Echo "Connecting to WMI"
ConnectToWMI

'Submit property bag
WScript.Echo "Returning Property Bag"
Call oAPI.Return(oBag)

Call CloseGlobalObjects

Sub ConnectToWMI()
  On Error Resume Next
  Dim sNameSpace, sHost, oWMIServices
  If bLocal Then 'means we're checking the health of WMI locally
    sNameSpace = "root\cimv2"
    sHost = "LOCAL"
    Set oWMIServices = oWMILocator.ConnectServer(".", sNameSpace,,,,,128)
    If Err.Number <> 0 Then
      WScript.Echo "WMI Error Return Code: " & Err.Number
      If Err.Number = "-2147023174" Then 'Windows Error 1722 - RPC Server is Unavailable
        Call oBag.AddValue("WMIReturnCode", 0)
      Else
        Call oBag.AddValue("WMIReturnCode", Err.Number)
      End If
    Else
      WScript.Echo "WMI Return Code: " & Err.Number
      Call oBag.AddValue("WMIReturnCode", 0)
      Set oWMIServices = Nothing      
    End If
  Else 'means we're checking the health of WMI remotely and need to get the host
    sHost = WScript.Arguments(1)
    sNameSpace = "root\cimv2"
    Set oWMIServices = oWMILocator.ConnectServer(sHost, sNameSpace,,,,,128)
    If Err.Number <> 0 Then
      WScript.Echo "WMI Error Return Code: " & Err.Number
      If Err.Number = "-2147023174" Then 'Windows Error 1722 - RPC Server is Unavailable
        Call oBag.AddValue("WMIReturnCode", 0)
      Else
        Call oBag.AddValue("WMIReturnCode", Err.Number)
      End If
    Else
      WScript.Echo "WMI Return Code: " & Err.Number
      Call oBag.AddValue("WMIReturnCode", 0)    
      Set oWMIServices = Nothing
    End If
  End If
End Sub

Sub CloseGlobalObjects()
    If IsObject(WshShell)         Then Set WshShell        = Nothing
    If IsObject(objFSO)         Then Set objFSO            = Nothing
    If IsObject(objWMIService)     Then Set objWMIService    = Nothing
    If IsObject(objDict)         Then Set objDict        = Nothing
    If IsObject(objRegEx)         Then Set objRegEx        = Nothing
    If IsObject(objNetwork)     Then Set objNetwork        = Nothing
    If IsObject(objArgs)         Then Set objArgs        = Nothing
    If IsObject(objXMLDoc)         Then Set objXMLDoc        = Nothing
End Sub]]></ScriptBody>
                <TimeoutSeconds>125</TimeoutSeconds>
              </DataSource>
            </MemberModules>
            <Composition>
              <Node ID="DS" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.PropertyBagData</OutputType>
      </DataSourceModuleType>
    </ModuleTypes>
    <MonitorTypes>
      <UnitMonitorType ID="Custom.Example.AgentlessDeviceMonitoring.MonitorType.WMIHealthCheck" Accessibility="Internal">
        <MonitorTypeStates>
          <MonitorTypeState ID="WMIHealthy" NoDetection="false" />
          <MonitorTypeState ID="WMIUnHealthy" 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="Arguments" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
          <xsd:element minOccurs="1" name="SyncTime" type="xsd:string" xmlns:xsd="https://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int" />
          <OverrideableParameter ID="Arguments" Selector="$Config/Arguments$" ParameterType="string" />
          <OverrideableParameter ID="SyncTime" Selector="$Config/SyncTime$" ParameterType="string" />
        </OverrideableParameters>
        <MonitorImplementation>
          <MemberModules>
            <DataSource ID="DS" TypeID="Custom.Example.AgentlessDeviceMonitoring.DataSource.WMIHealthCheck">
              <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
              <Arguments>$Config/Arguments$</Arguments>
              <SyncTime>$Config/SyncTime$</SyncTime>
            </DataSource>
            <ConditionDetection ID="CD1" TypeID="System!System.ExpressionFilter">
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Integer">Property[@Name='WMIReturnCode']</XPathQuery>
                  </ValueExpression>
                  <Operator>Equal</Operator>
                  <ValueExpression>
                    <Value Type="Integer">0</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
            </ConditionDetection>
            <ConditionDetection ID="CD2" TypeID="System!System.ExpressionFilter">
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Integer">Property[@Name='WMIReturnCode']</XPathQuery>
                  </ValueExpression>
                  <Operator>NotEqual</Operator>
                  <ValueExpression>
                    <Value Type="Integer">0</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
            </ConditionDetection>
          </MemberModules>
          <RegularDetections>
            <RegularDetection MonitorTypeStateID="WMIHealthy">
              <Node ID="CD1">
                <Node ID="DS" />
              </Node>
            </RegularDetection>
            <RegularDetection MonitorTypeStateID="WMIUnHealthy">
              <Node ID="CD2">
                <Node ID="DS" />
              </Node>
            </RegularDetection>
          </RegularDetections>
        </MonitorImplementation>
      </UnitMonitorType>
    </MonitorTypes>
  </TypeDefinitions>
  <Monitoring>
    <Discoveries>
      <Discovery ID="Custom.Example.AgentlessDeviceMonitoring.Discovery.Retail" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Retail" ConfirmDelivery="true" Remotable="true" Priority="Normal">
        <Category>Discovery</Category>
        <DiscoveryTypes>
          <DiscoveryRelationship TypeID="Custom.Example.AgentlessDeviceMonitoring.Relationship.RetailContainsStores" />
        </DiscoveryTypes>
        <DataSource ID="DS" TypeID="SC!Microsoft.SystemCenter.GroupPopulator">
          <RuleId>$MPElement$</RuleId>
          <GroupInstanceId>$Target/Id$</GroupInstanceId>
          <MembershipRules>
            <MembershipRule>
              <MonitoringClass>$MPElement[Name="Custom.Example.AgentlessDeviceMonitoring.Class.Stores"]$</MonitoringClass>
              <RelationshipClass>$MPElement[Name="Custom.Example.AgentlessDeviceMonitoring.Relationship.RetailContainsStores"]$</RelationshipClass>
            </MembershipRule>
          </MembershipRules>
        </DataSource>
      </Discovery>
      <Discovery ID="Custom.Example.AgentlessDeviceMonitoring.Discovery.Store.AgentlessRegister" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher" ConfirmDelivery="true" Remotable="true" Priority="Normal">
        <Category>Discovery</Category>
        <DiscoveryTypes>
          <DiscoveryClass TypeID="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" />
        </DiscoveryTypes>
        <DataSource ID="DS" TypeID="Custom.Example.AgentlessDeviceMonitoring.DataSource.DiscoverDevices">
          <IntervalSeconds>86400</IntervalSeconds>
          <RegisterOrAgentlessRegisterOrRegisterWatcher>AgentlessRegister</RegisterOrAgentlessRegisterOrRegisterWatcher>
          <StoreCode>$Target/Property[Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher"]/StoreCode$</StoreCode>
          <HostName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</HostName>
        </DataSource>
      </Discovery>
      <Discovery ID="Custom.Example.AgentlessDeviceMonitoring.Discovery.Store.RegisterRelationship" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.Register" ConfirmDelivery="true" Remotable="true" Priority="Normal">
        <Category>Discovery</Category>
        <DiscoveryTypes>
          <DiscoveryClass TypeID="Custom.Example.AgentlessDeviceMonitoring.Class.Store" />
          <DiscoveryRelationship TypeID="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsStoreRegister" />
        </DiscoveryTypes>
        <DataSource ID="DS" TypeID="Custom.Example.AgentlessDeviceMonitoring.DataSource.DiscoverStore">
          <IntervalSeconds>86400</IntervalSeconds>
          <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</ComputerName>
          <StoreCode>$Target/Property[Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store.Register"]/StoreCode$</StoreCode>
          <ServerOrClient>client</ServerOrClient>
        </DataSource>
      </Discovery>
      <Discovery ID="Custom.Example.AgentlessDeviceMonitoring.Discovery.Store.RegisterWatcher" Enabled="true" Target="Windows!Microsoft.Windows.Computer" ConfirmDelivery="true" Remotable="true" Priority="Normal">
        <Category>Discovery</Category>
        <DiscoveryTypes>
          <DiscoveryClass TypeID="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher" />
        </DiscoveryTypes>
        <DataSource ID="DS" TypeID="Windows!Microsoft.Windows.FilteredRegistryDiscoveryProvider">
          <ComputerName>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/NetworkName$</ComputerName>
          <RegistryAttributeDefinitions>
            <RegistryAttributeDefinition>
              <AttributeName>IsWatcher</AttributeName>
              <Path>SOFTWARE\Retail</Path>
              <PathType>0</PathType>
              <AttributeType>0</AttributeType>
            </RegistryAttributeDefinition>
            <RegistryAttributeDefinition>
              <AttributeName>StoreCode</AttributeName>
              <Path>SOFTWARE\Retail\Store</Path>
              <PathType>1</PathType>
              <AttributeType>1</AttributeType>
            </RegistryAttributeDefinition>
          </RegistryAttributeDefinitions>
          <Frequency>86400</Frequency>
          <ClassId>$MPElement[Name="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher"]$</ClassId>
          <InstanceSettings>
            <Settings>
              <Setting>
                <Name>$MPElement[Name="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher"]/StoreCode$</Name>
                <Value>$Data/Values/StoreCode$</Value>
              </Setting>
              <Setting>
                <Name>$MPElement[Name="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Name>
                <Value>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>
              </Setting>
              <Setting>
                <Name>$MPElement[Name="System!System.Entity"]/DisplayName$</Name>
                <Value>$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</Value>
              </Setting>
            </Settings>
          </InstanceSettings>
          <Expression>
            <SimpleExpression>
              <ValueExpression>
                <XPathQuery Type="String">Values/IsWatcher</XPathQuery>
              </ValueExpression>
              <Operator>Equal</Operator>
              <ValueExpression>
                <Value Type="String">True</Value>
              </ValueExpression>
            </SimpleExpression>
          </Expression>
        </DataSource>
      </Discovery>
      <Discovery ID="Custom.Example.AgentlessDeviceMonitoring.Discovery.Store.RegisterWatcherRelationship" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher" ConfirmDelivery="true" Remotable="true" Priority="Normal">
        <Category>Discovery</Category>
        <DiscoveryTypes>
          <DiscoveryClass TypeID="Custom.Example.AgentlessDeviceMonitoring.Class.Store" />
          <DiscoveryRelationship TypeID="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsStoreRegisterWatcher" />
        </DiscoveryTypes>
        <DataSource ID="DS" TypeID="Custom.Example.AgentlessDeviceMonitoring.DataSource.DiscoverStore">
          <IntervalSeconds>86400</IntervalSeconds>
          <ComputerName>$Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$</ComputerName>
          <StoreCode>$Target/Property[Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher"]/StoreCode$</StoreCode>
          <ServerOrClient>server</ServerOrClient>
        </DataSource>
      </Discovery>
      <Discovery ID="Custom.Example.AgentlessDeviceMonitoring.Discovery.Stores" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Stores" ConfirmDelivery="true" Remotable="true" Priority="Normal">
        <Category>Discovery</Category>
        <DiscoveryTypes>
          <DiscoveryRelationship TypeID="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoresContainsStore" />
        </DiscoveryTypes>
        <DataSource ID="DS" TypeID="SC!Microsoft.SystemCenter.GroupPopulator">
          <RuleId>$MPElement$</RuleId>
          <GroupInstanceId>$Target/Id$</GroupInstanceId>
          <MembershipRules>
            <MembershipRule>
              <MonitoringClass>$MPElement[Name="Custom.Example.AgentlessDeviceMonitoring.Class.Store"]$</MonitoringClass>
              <RelationshipClass>$MPElement[Name="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoresContainsStore"]$</RelationshipClass>
            </MembershipRule>
          </MembershipRules>
        </DataSource>
      </Discovery>
    </Discoveries>
    <Rules>
      <Rule ID="Custom.Example.AgentlessDeviceMonitoring.Rule.LogicalDisk.PercentFreeSpace" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ConfirmDelivery="true" Remotable="true" Priority="Normal" DiscardLevel="100">
        <Category>PerformanceCollection</Category>
        <DataSources>
          <DataSource ID="DS" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiPerfCounterProvider">
            <NameSpace>\\$Target/Property[Type="System!System.Entity"]/DisplayName$\root\cimv2</NameSpace>
            <Query>select PercentFreeSpace from Win32_PerfFormattedData_PerfDisk_LogicalDisk where Name = "C:"</Query>
            <Frequency>86350</Frequency>
            <ObjectName>LogicalDisk</ObjectName>
            <CounterName>% Free Space</CounterName>
            <InstanceName />
            <Value>$Data/Property[@Name='PercentFreeSpace']$</Value>
          </DataSource>
        </DataSources>
        <WriteActions>
          <WriteAction ID="WriteToDB" TypeID="SC!Microsoft.SystemCenter.CollectPerformanceData" />
          <WriteAction ID="WriteToDW" TypeID="SCDW!Microsoft.SystemCenter.DataWarehouse.PublishPerformanceData" />
        </WriteActions>
      </Rule>
      <Rule ID="Custom.Example.AgentlessDeviceMonitoring.Rule.LogicalDisk.TotalFreeSpace" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ConfirmDelivery="true" Remotable="true" Priority="Normal" DiscardLevel="100">
        <Category>PerformanceCollection</Category>
        <DataSources>
          <DataSource ID="DS" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiPerfCounterProvider">
            <NameSpace>\\$Target/Property[Type="System!System.Entity"]/DisplayName$\root\cimv2</NameSpace>
            <Query>select FreeMegabytes from Win32_PerfFormattedData_PerfDisk_LogicalDisk where Name = "C:"</Query>
            <Frequency>86400</Frequency>
            <ObjectName>LogicalDisk</ObjectName>
            <CounterName>Free Megabytes</CounterName>
            <InstanceName />
            <Value>$Data/Property[@Name='FreeMegabytes']$</Value>
          </DataSource>
        </DataSources>
        <WriteActions>
          <WriteAction ID="WriteToDB" TypeID="SC!Microsoft.SystemCenter.CollectPerformanceData" />
          <WriteAction ID="WriteToDW" TypeID="SCDW!Microsoft.SystemCenter.DataWarehouse.PublishPerformanceData" />
        </WriteActions>
      </Rule>
      <Rule ID="Custom.Example.AgentlessDeviceMonitoring.Rule.Memory.AvailableMBytes" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ConfirmDelivery="true" Remotable="true" Priority="Normal" DiscardLevel="100">
        <Category>PerformanceCollection</Category>
        <DataSources>
          <DataSource ID="DS" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiPerfCounterProvider">
            <NameSpace>\\$Target/Property[Type="System!System.Entity"]/DisplayName$\root\cimv2</NameSpace>
            <Query>select AvailableMBytes from Win32_PerfFormattedData_PerfOS_Memory</Query>
            <Frequency>1850</Frequency>
            <ObjectName>Memory</ObjectName>
            <CounterName>Available MBytes</CounterName>
            <InstanceName />
            <Value>$Data/Property[@Name='AvailableMBytes']$</Value>
          </DataSource>
        </DataSources>
        <WriteActions>
          <WriteAction ID="WriteToDB" TypeID="SC!Microsoft.SystemCenter.CollectPerformanceData" />
          <WriteAction ID="WriteToDW" TypeID="SCDW!Microsoft.SystemCenter.DataWarehouse.PublishPerformanceData" />
        </WriteActions>
      </Rule>
      <Rule ID="Custom.Example.AgentlessDeviceMonitoring.Rule.Memory.CommittedBytes" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ConfirmDelivery="true" Remotable="true" Priority="Normal" DiscardLevel="100">
        <Category>PerformanceCollection</Category>
        <DataSources>
          <DataSource ID="DS" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiPerfCounterProvider">
            <NameSpace>\\$Target/Property[Type="System!System.Entity"]/DisplayName$\root\cimv2</NameSpace>
            <Query>select CommittedBytes from Win32_PerfFormattedData_PerfOS_Memory</Query>
            <Frequency>1900</Frequency>
            <ObjectName>Memory</ObjectName>
            <CounterName>Committed Bytes</CounterName>
            <InstanceName />
            <Value>$Data/Property[@Name='CommittedBytes']$</Value>
          </DataSource>
        </DataSources>
        <WriteActions>
          <WriteAction ID="WriteToDB" TypeID="SC!Microsoft.SystemCenter.CollectPerformanceData" />
          <WriteAction ID="WriteToDW" TypeID="SCDW!Microsoft.SystemCenter.DataWarehouse.PublishPerformanceData" />
        </WriteActions>
      </Rule>
      <Rule ID="Custom.Example.AgentlessDeviceMonitoring.Rule.Memory.PercentCommittedBytesInUse" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ConfirmDelivery="true" Remotable="true" Priority="Normal" DiscardLevel="100">
        <Category>PerformanceCollection</Category>
        <DataSources>
          <DataSource ID="DS" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiPerfCounterProvider">
            <NameSpace>\\$Target/Property[Type="System!System.Entity"]/DisplayName$\root\cimv2</NameSpace>
            <Query>select PercentCommittedBytesInUse from Win32_PerfFormattedData_PerfOS_Memory</Query>
            <Frequency>1950</Frequency>
            <ObjectName>Memory</ObjectName>
            <CounterName>% Committed Bytes In Use</CounterName>
            <InstanceName />
            <Value>$Data/Property[@Name='PercentCommittedBytesInUse']$</Value>
          </DataSource>
        </DataSources>
        <WriteActions>
          <WriteAction ID="WriteToDB" TypeID="SC!Microsoft.SystemCenter.CollectPerformanceData" />
          <WriteAction ID="WriteToDW" TypeID="SCDW!Microsoft.SystemCenter.DataWarehouse.PublishPerformanceData" />
        </WriteActions>
      </Rule>
      <Rule ID="Custom.Example.AgentlessDeviceMonitoring.Rule.Process.PrivateBytes" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ConfirmDelivery="true" Remotable="true" Priority="Normal" DiscardLevel="100">
        <Category>PerformanceCollection</Category>
        <DataSources>
          <DataSource ID="DS" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiPerfCounterProvider">
            <NameSpace>\\$Target/Property[Type="System!System.Entity"]/DisplayName$\root\cimv2</NameSpace>
            <Query>select PrivateBytes from Win32_PerfFormattedData_PerfProc_Process where Name = "_Total"</Query>
            <Frequency>2000</Frequency>
            <ObjectName>Process</ObjectName>
            <CounterName>Private Bytes</CounterName>
            <InstanceName>_Total</InstanceName>
            <Value>$Data/Property[@Name='PrivateBytes']$</Value>
          </DataSource>
        </DataSources>
        <WriteActions>
          <WriteAction ID="WriteToDB" TypeID="SC!Microsoft.SystemCenter.CollectPerformanceData" />
          <WriteAction ID="WriteToDW" TypeID="SCDW!Microsoft.SystemCenter.DataWarehouse.PublishPerformanceData" />
        </WriteActions>
      </Rule>
      <Rule ID="Custom.Example.AgentlessDeviceMonitoring.Rule.Processor.PercentProcessorTime" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ConfirmDelivery="true" Remotable="true" Priority="Normal" DiscardLevel="100">
        <Category>PerformanceCollection</Category>
        <DataSources>
          <DataSource ID="DS" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiPerfCounterProvider">
            <NameSpace>\\$Target/Property[Type="System!System.Entity"]/DisplayName$\root\cimv2</NameSpace>
            <Query>select PercentProcessorTime from Win32_PerfFormattedData_PerfOS_Processor where Name="_Total"</Query>
            <Frequency>1800</Frequency>
            <ObjectName>Processor</ObjectName>
            <CounterName>% Processor Time</CounterName>
            <InstanceName>_Total</InstanceName>
            <Value>$Data/Property[@Name='PercentProcessorTime']$</Value>
          </DataSource>
        </DataSources>
        <WriteActions>
          <WriteAction ID="WriteToDB" TypeID="SC!Microsoft.SystemCenter.CollectPerformanceData" />
          <WriteAction ID="WriteToDW" TypeID="SCDW!Microsoft.SystemCenter.DataWarehouse.PublishPerformanceData" />
        </WriteActions>
      </Rule>
      <Rule ID="Custom.Example.AgentlessDeviceMonitoring.Rule.System.SystemUpTime" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ConfirmDelivery="true" Remotable="true" Priority="Normal" DiscardLevel="100">
        <Category>PerformanceCollection</Category>
        <DataSources>
          <DataSource ID="DS" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiPerfCounterProvider">
            <NameSpace>\\$Target/Property[Type="System!System.Entity"]/DisplayName$\root\cimv2</NameSpace>
            <Query>select SystemUpTime from Win32_PerfFormattedData_PerfOS_System</Query>
            <Frequency>21600</Frequency>
            <ObjectName>System</ObjectName>
            <CounterName>System Up Time</CounterName>
            <InstanceName />
            <Value>$Data/Property[@Name='SystemUpTime']$</Value>
          </DataSource>
        </DataSources>
        <WriteActions>
          <WriteAction ID="WriteToDB" TypeID="SC!Microsoft.SystemCenter.CollectPerformanceData" />
          <WriteAction ID="WriteToDW" TypeID="SCDW!Microsoft.SystemCenter.DataWarehouse.PublishPerformanceData" />
        </WriteActions>
      </Rule>
    </Rules>
    <Monitors>
      <UnitMonitor ID="Custom.Example.AgentlessDeviceMonitoring.Monitor.AgentlessRegisterWMIHealthCheck" Accessibility="Public" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Custom.Example.AgentlessDeviceMonitoring.MonitorType.WMIHealthCheck" ConfirmDelivery="true">
        <Category>AvailabilityHealth</Category>
        <OperationalStates>
          <OperationalState ID="WMIHealthy" MonitorTypeStateID="WMIHealthy" HealthState="Success" />
          <OperationalState ID="WMIUnHealthy" MonitorTypeStateID="WMIUnHealthy" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <IntervalSeconds>2050</IntervalSeconds>
          <Arguments>false $Target/Property[Type="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister"]/RegisterName$</Arguments>
          <SyncTime />
        </Configuration>
      </UnitMonitor>
      <UnitMonitor ID="Custom.Example.AgentlessDeviceMonitoring.Monitor.HighCPU" Accessibility="Public" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ParentMonitorID="Health!System.Health.PerformanceState" Remotable="true" Priority="Normal" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiBased.Performance.ConsecutiveSamplesThreshold" ConfirmDelivery="false">
        <Category>PerformanceHealth</Category>
        <OperationalStates>
          <OperationalState ID="ConditionFalse" MonitorTypeStateID="ConditionFalse" HealthState="Success" />
          <OperationalState ID="ConditionTrue" MonitorTypeStateID="ConditionTrue" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <NameSpace>\\$Target/Property[Type="System!System.Entity"]/DisplayName$\root\cimv2</NameSpace>
          <Query>select PercentProcessorTime from Win32_PerfFormattedData_PerfOS_Processor where Name="_Total"</Query>
          <Frequency>1800</Frequency>
          <ObjectName>Processor</ObjectName>
          <CounterName>% Processor Time</CounterName>
          <InstanceName>_Total</InstanceName>
          <Value>$Data/Property[@Name='PercentProcessorTime']$</Value>
          <Threshold>80</Threshold>
          <Direction>greater</Direction>
          <NumSamples>3</NumSamples>
        </Configuration>
      </UnitMonitor>
      <UnitMonitor ID="Custom.Example.AgentlessDeviceMonitoring.Monitor.LowAvailDiskSpace" Accessibility="Public" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiBased.Performance.ThresholdMonitorType" ConfirmDelivery="false">
        <Category>PerformanceHealth</Category>
        <OperationalStates>
          <OperationalState ID="OverThreshold" MonitorTypeStateID="OverThreshold" HealthState="Success" />
          <OperationalState ID="UnderThreshold" MonitorTypeStateID="UnderThreshold" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <NameSpace>\\$Target/Property[Type="System!System.Entity"]/DisplayName$\root\cimv2</NameSpace>
          <Query>select FreeMegabytes from Win32_PerfFormattedData_PerfDisk_LogicalDisk where Name = "C:"</Query>
          <Frequency>86400</Frequency>
          <ObjectName>LogicalDisk</ObjectName>
          <CounterName>Free Megabytes</CounterName>
          <InstanceName />
          <Value>$Data/Property[@Name='FreeMegabytes']$</Value>
          <Threshold>125</Threshold>
        </Configuration>
      </UnitMonitor>
      <UnitMonitor ID="Custom.Example.AgentlessDeviceMonitoring.Monitor.LowDiskSpace" Accessibility="Public" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiBased.Performance.ThresholdMonitorType" ConfirmDelivery="false">
        <Category>PerformanceHealth</Category>
        <OperationalStates>
          <OperationalState ID="OverThreshold" MonitorTypeStateID="OverThreshold" HealthState="Success" />
          <OperationalState ID="UnderThreshold" MonitorTypeStateID="UnderThreshold" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <NameSpace>\\$Target/Property[Type="System!System.Entity"]/DisplayName$\root\cimv2</NameSpace>
          <Query>select PercentFreeSpace from Win32_PerfFormattedData_PerfDisk_LogicalDisk where Name = "C:"</Query>
          <Frequency>86350</Frequency>
          <ObjectName>LogicalDisk</ObjectName>
          <CounterName>% Free Space</CounterName>
          <InstanceName />
          <Value>$Data/Property[@Name='PercentFreeSpace']$</Value>
          <Threshold>5</Threshold>
        </Configuration>
      </UnitMonitor>
      <UnitMonitor ID="Custom.Example.AgentlessDeviceMonitoring.Monitor.LowMemory" Accessibility="Public" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ParentMonitorID="Health!System.Health.PerformanceState" Remotable="true" Priority="Normal" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiBased.Performance.ThresholdMonitorType" ConfirmDelivery="false">
        <Category>PerformanceHealth</Category>
        <OperationalStates>
          <OperationalState ID="UnderThreshold" MonitorTypeStateID="UnderThreshold" HealthState="Success" />
          <OperationalState ID="OverThreshold" MonitorTypeStateID="OverThreshold" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <NameSpace>\\$Target/Property[Type="System!System.Entity"]/DisplayName$\root\cimv2</NameSpace>
          <Query>select PercentCommittedBytesInUse from Win32_PerfFormattedData_PerfOS_Memory</Query>
          <Frequency>1900</Frequency>
          <ObjectName>Memory</ObjectName>
          <CounterName>PercentCommittedBytesInUse</CounterName>
          <InstanceName />
          <Value>$Data/Property[@Name='PercentCommittedBytesInUse']$</Value>
          <Threshold>95</Threshold>
        </Configuration>
      </UnitMonitor>
      <UnitMonitor ID="Custom.Example.AgentlessDeviceMonitoring.Monitor.PingCheck" Accessibility="Public" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" RunAs="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile" TypeID="Windows!Microsoft.Windows.WmiBased.Performance.ConsecutiveSamplesThreshold" ConfirmDelivery="false">
        <Category>AvailabilityHealth</Category>
        <OperationalStates>
          <OperationalState ID="ConditionFalse" MonitorTypeStateID="ConditionFalse" HealthState="Success" />
          <OperationalState ID="ConditionTrue" MonitorTypeStateID="ConditionTrue" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <NameSpace>root\cimv2</NameSpace>
          <Query>Select StatusCode from Win32_PingStatus Where Address ='$Target/Property[Type="System!System.Entity"]/DisplayName$'</Query>
          <Frequency>800</Frequency>
          <ObjectName>Register Ping Status</ObjectName>
          <CounterName>PingResponse</CounterName>
          <InstanceName />
          <Value>$Data/Property[@Name='StatusCode']$</Value>
          <Threshold>0</Threshold>
          <Direction>greater</Direction>
          <NumSamples>4</NumSamples>
        </Configuration>
      </UnitMonitor>
      <UnitMonitor ID="Custom.Example.AgentlessDeviceMonitoring.Monitor.RegisterWatcherWMIHealthCheck" Accessibility="Public" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher" ParentMonitorID="Health!System.Health.AvailabilityState" Remotable="true" Priority="Normal" TypeID="Custom.Example.AgentlessDeviceMonitoring.MonitorType.WMIHealthCheck" ConfirmDelivery="true">
        <Category>AvailabilityHealth</Category>
        <OperationalStates>
          <OperationalState ID="WMIHealthy" MonitorTypeStateID="WMIHealthy" HealthState="Success" />
          <OperationalState ID="WMIUnHealthy" MonitorTypeStateID="WMIUnHealthy" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <IntervalSeconds>300</IntervalSeconds>
          <Arguments>true</Arguments>
          <SyncTime />
        </Configuration>
      </UnitMonitor>
      <DependencyMonitor ID="Custom.Example.AgentlessDeviceMonitoring.Monitor.RetailStores" Accessibility="Internal" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Retail" ParentMonitorID="Health!System.Health.EntityState" Remotable="true" Priority="Normal" RelationshipType="Custom.Example.AgentlessDeviceMonitoring.Relationship.RetailContainsStores" MemberMonitor="Health!System.Health.EntityState">
        <Category>Custom</Category>
        <Algorithm>WorstOf</Algorithm>
        <MemberUnAvailable>Error</MemberUnAvailable>
      </DependencyMonitor>
      <DependencyMonitor ID="Custom.Example.AgentlessDeviceMonitoring.Monitor.StoreAgentlessRegister" Accessibility="Internal" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store" ParentMonitorID="Health!System.Health.EntityState" Remotable="true" Priority="Normal" RelationshipType="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsAgentlessStoreRegister" MemberMonitor="Health!System.Health.EntityState">
        <Category>Custom</Category>
        <Algorithm>Percentage</Algorithm>
        <AlgorithmParameter>20</AlgorithmParameter>
        <MemberUnAvailable>Error</MemberUnAvailable>
      </DependencyMonitor>
      <DependencyMonitor ID="Custom.Example.AgentlessDeviceMonitoring.Monitor.StoreRegister" Accessibility="Internal" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store" ParentMonitorID="Health!System.Health.EntityState" Remotable="true" Priority="Normal" RelationshipType="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsStoreRegister" MemberMonitor="Health!System.Health.EntityState">
        <Category>Custom</Category>
        <Algorithm>Percentage</Algorithm>
        <AlgorithmParameter>20</AlgorithmParameter>
        <MemberUnAvailable>Error</MemberUnAvailable>
      </DependencyMonitor>
      <DependencyMonitor ID="Custom.Example.AgentlessDeviceMonitoring.Monitor.StoreRegisterWatcher" Accessibility="Internal" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Store" ParentMonitorID="Health!System.Health.EntityState" Remotable="true" Priority="Normal" RelationshipType="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsStoreRegisterWatcher" MemberMonitor="Health!System.Health.EntityState">
        <Category>Custom</Category>
        <Algorithm>WorstOf</Algorithm>
        <MemberUnAvailable>Error</MemberUnAvailable>
      </DependencyMonitor>
      <DependencyMonitor ID="Custom.Example.AgentlessDeviceMonitoring.Monitor.StoresStore" Accessibility="Internal" Enabled="true" Target="Custom.Example.AgentlessDeviceMonitoring.Class.Stores" ParentMonitorID="Health!System.Health.EntityState" Remotable="true" Priority="Normal" RelationshipType="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoresContainsStore" MemberMonitor="Health!System.Health.EntityState">
        <Category>Custom</Category>
        <Algorithm>Percentage</Algorithm>
        <AlgorithmParameter>20</AlgorithmParameter>
        <MemberUnAvailable>Error</MemberUnAvailable>
      </DependencyMonitor>
    </Monitors>
  </Monitoring>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Class.Retail">
          <Name>Retail Environment</Name>
          <Description>Central node for the retail environment (distributed application)</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Class.Store">
          <Name>Store</Name>
          <Description>Entity representing a single store</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Class.Store" SubElementID="StoreCode">
          <Name>Store Code</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister">
          <Name>Agentless Store Register</Name>
          <Description>Class for registers that don't have an OpsMgr agent</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" SubElementID="RegisterName">
          <Name>Register Name</Name>
          <Description>Register Name</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Class.Store.AgentlessRegister" SubElementID="StoreCode">
          <Name>Store Code</Name>
          <Description>Store Code</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Class.Store.Register">
          <Name>Store Register</Name>
          <Description>Class for registers that contain an agent</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Class.Store.Register" SubElementID="StoreCode">
          <Name>Store Code</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher">
          <Name>Store Register Watcher</Name>
          <Description>Server in the stores that is used to monitor the registers.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Class.Store.RegisterWatcher" SubElementID="StoreCode">
          <Name>Store Code</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Class.Stores">
          <Name>Stores</Name>
          <Description>Rollup class representing all stores in the retail environment</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.DataSource.DiscoverDevices">
          <Name>Discover Devices Data Source</Name>
          <Description>Used to discover the agentless register, register, and register watcher classes.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.DataSource.DiscoverDevices" SubElementID="IntervalSeconds">
          <Name>IntervalSeconds</Name>
          <Description>The interval at which the discovery will be run</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.DataSource.DiscoverDevices" SubElementID="RegisterOrAgentlessRegisterOrRegisterWatcher">
          <Name>RegisterOrAgentlessRegisterOrRegisterWatcher</Name>
          <Description>Specify which type of instance this will be</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.DataSource.DiscoverDevices" SubElementID="StoreCode">
          <Name>StoreCode</Name>
          <Description>The StoreCode variable</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.DataSource.DiscoverStore">
          <Name>Discover Store Data Source</Name>
          <Description>Data Source to discover stores</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.DataSource.DiscoverStore" SubElementID="IntervalSeconds">
          <Name>IntervalSeconds</Name>
          <Description>Discover Store Interval</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.DataSource.WMIHealthCheck">
          <Name>WMI Health Check Data Source</Name>
          <Description>Checks the health of WMI locally or remotely</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Discovery.Retail">
          <Name>Retail Discovery</Name>
          <Description>Discovers the top level node of the distributed application.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Discovery.Store.AgentlessRegister">
          <Name>Agentless Register Discovery</Name>
          <Description>Discovery to populate the agentless register class</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Discovery.Store.RegisterRelationship">
          <Name>Store Register Relationship Discovery</Name>
          <Description>Discovers the relationship between the store and the store register.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Discovery.Store.RegisterWatcher">
          <Name>Register Watcher Discovery</Name>
          <Description>Discovers the watcher nodes.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Discovery.Store.RegisterWatcherRelationship">
          <Name>Store Register Watcher Relationship</Name>
          <Description>Discovers the relationship between the Store and the Register Watcher in the Store.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Discovery.Stores">
          <Name>Stores Discovery</Name>
          <Description>Populates Stores Node of the distributed application.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring">
          <Name>Agentless Device Monitoring</Name>
          <Description>Agentless Device Monitoring Management Pack</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.MonitorType.WMIHealthCheck">
          <Name>WMI Health Check Monitor Type</Name>
          <Description>Determines if WMI is health locally or remotely.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Relationship.RegisterWatcherHostsAgentlessRegister">
          <Name>Register Watcher Hosts Agentless Register Relationship</Name>
          <Description>Relationship for the RegisterWatcher to AgentlessRegister</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Relationship.RetailContainsStores">
          <Name>Retail Contains Stores Relationship</Name>
          <Description>Relationship for the Retail to Stores</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsAgentlessStoreRegister">
          <Name>Store Contains Agentless Store Register</Name>
          <Description>Relationship for the Store to Agentless Store Register</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsStoreRegister">
          <Name>Store Contains Store Register Relationship</Name>
          <Description>Relationship for the Store to Store Register</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoreContainsStoreRegisterWatcher">
          <Name>Store Contains Store Register Watcher</Name>
          <Description>Relationship for the Store to Store Register Watcher</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Relationship.StoresContainsStore">
          <Name>Stores Contains Store Relationship</Name>
          <Description>Relationship for the Stores to Store</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Rule.LogicalDisk.PercentFreeSpace">
          <Name>LogicalDisk - % Free Space</Name>
          <Description>Collects the LogicalDisk - % Free Space counter from a remote machine</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Rule.LogicalDisk.TotalFreeSpace">
          <Name>LogicalDisk - Total Free Space</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Rule.Memory.AvailableMBytes">
          <Name>Memory - Available MBytes</Name>
          <Description>Collects the Memory - Available MBytes counter from a remote machine</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Rule.Memory.CommittedBytes">
          <Name>Memory - Committed Bytes</Name>
          <Description>Collects the Memory - Committed Bytes counter from a remote machine</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Rule.Memory.PercentCommittedBytesInUse">
          <Name>Memory - % Committed Bytes In Use</Name>
          <Description>Collects the Memory - % Committed Bytes In Use counter from a remote machine</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Rule.Process.PrivateBytes">
          <Name>Process - Private Bytes - _Total</Name>
          <Description>Collection rule to collect Process - Private Bytes - _Total counter</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Rule.Processor.PercentProcessorTime">
          <Name>Processor - % Processor Time</Name>
          <Description>Collects the Processor - % Processor Time counter from a remote machine</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Rule.System.SystemUpTime">
          <Name>System - System Up Time</Name>
          <Description>Collects the System - System Up Time counter from a remote machine</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.RunAS.Profile">
          <Name>Agentless Device Monitoring RunAs Profile</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.AgentlessRegisterWMIHealthCheck">
          <Name>Agentless Monitor WMI Health Check</Name>
          <Description>Monitor that checks WMI from a watcher node to determine health</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.AgentlessRegisterWMIHealthCheck" SubElementID="WMIHealthy">
          <Name>WMIHealthy</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.AgentlessRegisterWMIHealthCheck" SubElementID="WMIUnHealthy">
          <Name>WMIUnHealthy</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.HighCPU">
          <Name>High CPU Utilization Monitor</Name>
          <Description>Uses consecutive samples to determine high cpu utilization.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.HighCPU" SubElementID="ConditionFalse">
          <Name>ConditionFalse</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.HighCPU" SubElementID="ConditionTrue">
          <Name>ConditionTrue</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.LowAvailDiskSpace">
          <Name>Low Available Disk Space on C:</Name>
          <Description>Watches for the absolute value of low drive space on a remote computer</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.LowAvailDiskSpace" SubElementID="OverThreshold">
          <Name>OverThreshold</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.LowAvailDiskSpace" SubElementID="UnderThreshold">
          <Name>UnderThreshold</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.LowDiskSpace">
          <Name>Low Disk Space on C:</Name>
          <Description>Watches for low drive space on a remote computer</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.LowDiskSpace" SubElementID="OverThreshold">
          <Name>OverThreshold</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.LowDiskSpace" SubElementID="UnderThreshold">
          <Name>UnderThreshold</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.LowMemory">
          <Name>Agentless Low Memory Monitor</Name>
          <Description>Low memory monitor which uses WMI remotely.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.LowMemory" SubElementID="OverThreshold">
          <Name>OverThreshold</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.LowMemory" SubElementID="UnderThreshold">
          <Name>UnderThreshold</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.PingCheck">
          <Name>Ping Check</Name>
          <Description>Does a ping using WMI on a remote target</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.PingCheck" SubElementID="ConditionFalse">
          <Name>ConditionFalse</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.PingCheck" SubElementID="ConditionTrue">
          <Name>ConditionTrue</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.RegisterWatcherWMIHealthCheck">
          <Name>Register Watcher WMI Health Check Monitor</Name>
          <Description>Monitors WMI locally to determine health.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.RegisterWatcherWMIHealthCheck" SubElementID="WMIHealthy">
          <Name>WMIHealthy</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.RegisterWatcherWMIHealthCheck" SubElementID="WMIUnHealthy">
          <Name>WMIUnHealthy</Name>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.RetailStores">
          <Name>Retail to Stores Dependency Monitor</Name>
          <Description>Rollup monitor for the Stores to Retail relationship.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.StoreAgentlessRegister">
          <Name>Store to Agentless Register Dependency Monitor</Name>
          <Description>Rollup monitor for the Store to AgentlessRegister relationship.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.StoreRegister">
          <Name>Store to Store Register Dependency Monitor</Name>
          <Description>Rollup for the Store to Store Register relationship</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.StoreRegisterWatcher">
          <Name>Store to Register Watcher Dependency Monitor</Name>
          <Description>Rollup for the Store to Register Watcher Relationship.</Description>
        </DisplayString>
        <DisplayString ElementID="Custom.Example.AgentlessDeviceMonitoring.Monitor.StoresStore">
          <Name>Stores to Store Dependency Monitor</Name>
          <Description>Rollup monitor for the Store to Stores dependency monitor.</Description>
        </DisplayString>
      </DisplayStrings>
      <KnowledgeArticles></KnowledgeArticles>
    </LanguagePack>
  </LanguagePacks>
</ManagementPack>

 

*Note, I did make some registry tweaks on my watcher nodes. I noticed that if several agentless registers were offline the workflows would unload on the watcher. These settings stopped it from happening so I recommend testing these out if you run into that issue.

Registry Tweaks on Watcher Node (used to prevent workflows from being unloaded due to offline registers)

  • Key: ”HKLM:\SYSTEM\CurrentControlSet\Services\HealthService\Parameters”

    • DWORD Value: "WorkFlowErrorReloadAllocations"
    • Value = 100
  • Key: “HKLM:\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Modules\Global\Command Executer”

    • DWORD Value:  "AsyncProcessLimit"
    • Value = 5
  • Key: ”HKLM:\SOFTWARE\Microsoft\Microsoft Operations Manager\3.0\Modules\Global\Command Executer”

    • DWORD Value: "ProcessLimit"
    • Value = 5

Custom.Example.AgentlessDeviceMonitoring.renametoxml