Tag Archives: MimboloveMP Authoring

Location, Location, Location. Part 1

Written by Tao Yang

iStock_000006260161SmallYes, I am starting to write a 3 part series on this topic: Location, Location, Location. It is not about real estate business – It would be silly for me to wait until I’ve received MVP award to become a real estate salesman, right? Smile

This series is all about tracking physical location for Windows based mobile devices (tablets and laptops). It involves windows tablets/ laptops, OpsMgr 2012, dashboards, Google Maps and Windows Location Platform. Does this interest you? if so, please continue reading. Smile


When I started designing the OpsMgr 2012 infrastructure for my employer about a 18 months ago, during requirements gathering phase, Windows tablets were seriously in the scope of devices to be monitored by OpsMgr. At that time, I thought it doesn’t make any sense having OpsMgr 2012 to monitor thousands of Windows tablets. Now, 18 months later, with more and more organisations started to adopt Windows 8 tablets into corporate environments, I thought I’d spend a little bit time on this and see what we can get out of OpsMgr if Windows 8 tablets and laptops are being monitored in OpsMgr 2012.

Since most of the modern devices are location aware, wouldn’t it be nice if we can use SCOM to monitor their physical locations? I had this idea after I posted the Google Map dashboard couple of months ago. Now that FIFA World Cup is over and my life is back to normal, I finally had time to spend on it.


One important aspect of tablets and laptops is being mobile. physical security has always been a big concern for organisations. By utilising Windows Location Framework, OpsMgr agent and dashboards, I managed to produce 3 scenarios in my lab. I will cover each one of them in one part of this series:

  • Part 1: Track Windows 8 computers current location (real time)
  • Part 2: Monitor the physical location (In case it’s gone M.I.A)
  • Part 3: Track historical locations (where have they been?)

Note: The management packs I created for this experiment can be downloaded at the end of part 3.


To prepare my lab of these monitoring scenarios, I had to setup the following pre-requisites:

01. Setup DirectAccess for my home lab so my Surface Pro 2 would automatically connect to my lab when it is not at home (i.e. via a 4G connection).

02. Rebuilt my Surface Pro 2 to Windows 8.1 Enterprise edition. – As DirectAccess client is only available in Enterprise edition.

03. Made sure Windows Location Platform is enabled on Surface Pro 2. This is configured in Control Panel:


and Privacy settings:


We can also use GPO to enable it: Computer Configuration\Administrative Templates\Windows Components\Location and Sensors


04. Make sure WinRM is enabled on the mobile devices. A PowerShell script I used in a dashboard uses WinRM to get the devices location report.

Additionally, I already have OpsMgr 2012 R2 agent installed on my Surface Pro 2 and it is reporting to my home management group. The latest OpsMgr 2012 Update Rollup (SP1 UR6 or R2 UR2) also needs to be installed in order to use the new PowerShell dashboard widgets.

Limitations – Lack of GPS Devices

When I started working on this experiment, I found my Surface Pro 2 does not have a GPS receiver (And Surface Pro 3 also doesn’t have it Sad smile). Then I also found most of the Windows 8 tablets currently out in the market don’t have GPS receivers built-in. I haven’t been able to find one with GPS receivers. Therefore, the location data provided by Windows Location API come from Wi-Fi triangulation, IP address resolution and cellular network triangulation, which is probably less accurate than GPS data (More details can be found on MSDN:http://msdn.microsoft.com/en-us/library/windows/apps/hh464919.aspx). I didn’t want to purchase a Windows 8 compatible GPS receiver because I have no real need for it after this experiment, and also tried to use my Android phone as a bluetooth GPS receiver to the Windows 8 devices, but I couldn’t make it work.

Having said that, based on my experience, the data received from cellular and Wi-Fi network is fairly accurate for me. When I’m at home, the location on the map is my neighbour across the road, which is less than 20 metres away from my desk.

Scenario 1: Where is the the device currently located?

I created a fairly simply dashboard in OpsMgr to pinpoint the current location of a selected:


(Sorry guys, I pixelated the map as I don’t really want to post my home location on the Internet Smile).

As you can see, this dashboard only contains 2 widgets. the left widget is a state widget targeting “Windows Client 8 Computer” class:




Note: Because I’m referencing Windows 8 computers, I have Windows 8 management packs (version 6.0.7024.0) loaded in my management group. Since all the client computers in my lab are running 8.1, I have also installed the Windows 8 Addendum MP from Kevin Holman as the original one does not discover Windows 8.1.

The widget on the right is a PowerShell Web Browser widget (shipped with SP1 UR6 and R2 UR2). This widget runs the script below:

$dataObject = $ScriptContext.CreateInstance("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/Request")
$dataObject["BaseUrl"]="<a href="http://maps.google.com/maps&quot;">http://maps.google.com/maps"</a>
$parameterCollection = $ScriptContext.CreateCollection("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/UrlParameter[]")
foreach ($globalSelectedItem in $globalSelectedItems)
$globalSelectedItemInstance = Get-SCOMClassInstance -Id $globalSelectedItem["Id"]
$DNSNameProperty = $globalSelectedItemInstance.GetMonitoringProperties() | Where-Object {$_.name -match "^DNSName$"}
$DNSName = $globalSelectedItemInstance.GetMonitoringPropertyValue($DNSNameProperty)

#Get Coordinates via WinRM

#Create a WinRM session to the remote computer
$RemoteSession = New-PSSession -ComputerName $DNSName
$objRemoteLoc = Invoke-command -scriptblock {
# Windows Location API
$mylocation = new-object -comObject LocationDisp.LatLongReportFactory

# Get Status
$mylocationstatus = $mylocation.status

#try again if first attemp is not successful
if ($mylocationstatus -ne 4)
#Remove-Variable mylocation
Start-Sleep -Seconds 5
$mylocation = new-object -comObject LocationDisp.LatLongReportFactory
$mylocationstatus = $mylocation.status
If ($mylocationstatus -eq 4)
# Windows Location Status returns 4, so we're "Running"
# Get Latitude and Longitude from LatlongReport property
$latitude = $mylocation.LatLongReport.Latitude
$longitude = $mylocation.LatLongReport.Longitude
$altitude = $mylocation.LatLongReport.altitude
$errorRadius = $mylocation.LatLongReport.ErrorRadius

#Pass invalid values if location is not detected
If ($latitude -eq $null -or $longitude -eq $null)
$bValidLoc = $false
} else {
$bValidLoc = $true

#Return Data
$objLoc = New-Object psobject
Add-Member -InputObject $objLoc -membertype noteproperty -name "ValidLocation" -value $bValidLoc
Add-Member -InputObject $objLoc -membertype noteproperty -name "LocationStatus" -value $mylocationstatus
Add-Member -InputObject $objLoc -membertype noteproperty -name "latitude" -value $latitude
Add-Member -InputObject $objLoc -membertype noteproperty -name "longitude" -value $longitude
Add-Member -InputObject $objLoc -membertype noteproperty -name "altitude" -value $altitude
Add-Member -InputObject $objLoc -membertype noteproperty -name "errorRadius" -value $errorRadius
} -Session $RemoteSession
$latitude = $objRemoteLoc | select -ExpandProperty latitude
$longitude = $objRemoteLoc | select -ExpandProperty longitude
$ValidLocation = $objRemoteLoc | select -ExpandProperty ValidLocation
$parameter = $ScriptContext.CreateInstance("xsd://Microsoft.SystemCenter.Visualization.Component.Library!Microsoft.SystemCenter.Visualization.Component.Library.WebBrowser.Schema/UrlParameter")
$parameter["Name"] = "q"
$parameter["Value"] = "loc:" + $latitude + "+" + $longitude
Remove-PSSession $RemoteSession
$dataObject["Parameters"]= $parameterCollection

This script establishes a PS Remote session (WinRM) and retrieve computer’s coordinates using LocationDisp.LatLongReportFactory COM object. the coordinates then get passed back to the local PS session and then got pinned on Google Map based on the latitude and longitude data.

This concludes part 1 of the series. Please continue to Part 2.

OpsMgr 2012 Self Maintenance Management Pack

Written by Tao Yang

This blog has been a bit quiet lately because of 2 reasons: FIFA World Cup and I’ve been updating the OpsMgr 2012 Self Maintenance MP. 🙂

What’s new in version

  • Corrected spelling mistake in Management Server maintenance mode watcher display name
  • Updated knowledge article for OpsMgr 2012 Self Maintenance Detect Manually Closed Monitor Alerts Rule
  • Additional Monitor: OpsMgr 2012 Self Maintenance Management Server Default Action Account OpsMgr Admin Privilege Monitor
  • Additional Monitor: OpsMgr 2012 Self Maintenance Management Server Default Action Account Local Admin Privilege Monitor
  • Additional Rule: OpsMgr 2012 Self Maintenance Obsolete Management Pack Alias Detection Rule
  • Additional Agent Task: Get Workflow Name(ID)
  • Additional Agent Task: Reset Monitor Health State
  • Additional Agent Task: Remove Obsolete MP References

Additional Monitors to check if management servers action account has local admin on management servers and OpsMgr privileges

I often get emails from people who are having issues configuring workflows in the Self Maintenance MP. I found one of a common issues is that the default action account for management servers does not required privileges. Therefore I created 2 monitors in this release to monitor if the MS action account has local administrator and OpsMgr administrator privileges.



Additional Rule: OpsMgr 2012 Self Maintenance Obsolete Management Pack Alias Detection Rule

As I mentioned in my previous post PowerShell Script: Remove Obsolete References from Unsealed OpsMgr Management Packs, I’ve created a rule that detects obsolete MP references in unsealed management packs. The difference between the stand alone script (from previous post) and this rule is, this rule would only detect obsolete MP references, it will not try to remove them. Operators can use the “Remove Obsolete MP References” agent task manually remove them (or using the standalone script I published earlier).


Additional Agent Task: Remove Obsolete MP References

This task targets All Management Servers Resource Pool and can be used in conjunction with the Obsolete Management Pack Alias Detection Rule to delete obsolete MP references from unsealed management packs.


Additional Agent Tasks: “Get Workflow Name(ID)” and “Reset Monitor Health State”


Previously, few people have suggested me to provide a method to reset all instances of a particular monitor. Recently, Cameron Fuller showed me a script from Matthew Dowst’s blog post and suggested me to add this into the Self Maintenance MP.

The script from Matthew’s blog resets health state of all instances of monitors with a given display name. In my opinion, this is not granular enough as there are monitors sharing same display name, we can not use display name to uniquely identify a particular monitor.



Therefore, when I was writing the script for the Reset Monitor Health State agent task, I used monitor name instead of display name. However, since the monitor name is actually not viewable in the Operations Console, I had to create another agent task to get the name of a workflow (monitors, rules and discoveries).

i.e. let’s use the “Computer Browser Service Health” monitors as an example.

Get the monitor(s) using SCOM PowerShell Module:


In my environment, there are 2 monitors that have the same display name. the actual monitor name is highlighted in the red rectangles. the names are unique. It is actually the MP element ID in the management pack where the monitor is coming from:


So in order to use the “Reset Monitor Health State” task, operators firstly need to identify the monitor name (MP element ID), then paste it into an override field of the task. To make it easier, we can use the “Get Workflow Name(ID)” agent task to get the name:


Then copy and paste the monitor name into the “MonitorName” override parameter of the “Reset Monitor Health State”:




Where to find the detailed information for these additional items?

I have only covered a very high level overview of these additional workflows in this post. the detailed information can be found in the updated MP documentation (From Section 5.2.24 to 5.2.29):


Please make sure you read each section before enabling / using each workflow!


I’d like to thank Cameron Fuller, Bob Cornelissen and Raphael Burri for the suggestions and testing effort. Also, thanks Matthew Dowst for the original scripts in his posts.

Lastly, if you have suggestions or issues / questions that are not documented in the documentation, please feel free to contact me.


Updated OpsMgr 2012 Alert Update Connector Management Pack

Written by Tao Yang

I recently implemented OpsMgr 2012 Alert Update Connector in the new OpsMgr 2012 environments that I’m building. I have previously blogged my way of generating AUC’s configuration XML.

Now in my environment, AUC is playing a critical role in the alert logging process, it needs to be highly available. nothing will get logged to the ticketing system if AUC is not running. The unsealed management pack that came with AUC monitors each individual instance of Alert Update Connector service. It generates a critical alert when the service is not running while the start mode is configured to Automatic. However, in my opinion, this does not reflect the real health condition of AUC. Since we can install Alert Update Connector service on multiple computers, the connector should be considered as healthy when there is one instance (and one instance only) of the Alert Update Connector service running.

Therefore, I have updated the management pack. I have made the following changes to the original MP:

01. Bug fix in the VBScript used in Alert Update Connector Discovery

I have installed the Alert Update Connector service on all the management servers. I also have few Orchestrator runbook servers being monitored agentlessly because they are running runbooks which require OpsMgr 2007 R2 integration pack and console, so I can’t installed OpsMgr 2012 R2 agents on them. After imported the original management pack, I noticed Alert Update Connector services have also been discovered on these Orchestrator runbook servers.

The bug is highlighted below:


The discovery is configured to be remotable, but when performing the WMI query for the service, it is always querying the local computer where the discovery script is running. This is why the Alert Update Connector service has been incorrectly discovered on agentless monitored computers. This is an easy fix. since the target computer name has already been passed to the script, in line 91, “strComputer” needs be changed to “TargetComputer”.

02. Updated the frequency for Alert Update Connector Discovery

In the original MP, this discovery runs once per hour. I have updated it every 12 hours.

03. Additional Monitor: Alert Connector Services Overall Status Monitor


This monitor is targeting the Alert Update Connector class (which is managed by All Management Servers Resource Pool), and checks number of running instances of Alert Update Connector service. it generates a critical alert when the running instance does not equal to 1.


This monitor also has 2 recovery tasks


When there are no running instances, the recovery task “Start One Instance of Alert Update Connector Service” will try to start 1 instance of this service. When the number of running instances is greater than 1, the recovery task “Stop and Disable additional running instances” will stop and disable all but 1 running instances.

The script execution results can be viewed in Health Explorer:



Since the connector class is managed by AMSRP, the monitor workflow will run on a management server. If you only have the Alert Update Connector services installed on management servers, and the management server’s default action account should have local admin rights on the management servers, no additional configuration is required. however, if you have Alert update connector service installed on other servers where the default management servers action account does not have local admin rights, you may need to configure the Run-As profile defined in this MP:


03. Additional Groups

I’ve created 2 additional groups:

  • Alert Update Connector Services Computer group
  • Alert Update Connector Services Instance Group



04. Additional Override: Disabled Alert Generation for the “Connector Service Status” monitor.



I’m just trying to reduce the noise. Since the newly created overall status monitor will be generating alerts as well, I don’t think we need another one.

05. Removed the console task “Show Connector UI”

This task hardcoded the ConnectorConfiguration.exe to C:\AlertUpdateConnectorUI, and I’m not using this GUI tool in my environment (refer to my previous post). Therefore I have removed it from the MP.

I have changed the MP version to I have also converted the original MP to a VSAE project. In the project, I have chopped the MP components into many fragments.


You can download both sealed and unsealed version of this MP, as well as the VSAE project (to make your life easier if you want to update it to suit your needs). However, I won’t include the key I used in for this MP. if you decided to update and seal it again, please use another key.


Management Pack for the SCOM 2012 Maintenance Mode Scheduler

Written by Tao Yang

I’ve been working on a SCOM management pack during my spare time over the last couple of weeks. This management pack provides some basic monitoring for the SCOM 2012 Maintenance Mode Scheduler Version 2 developed by Tim McFadden (http://www.scom2k7.com/scom-2012-maintenance-mode-scheduler-2/).

The purpose of this MP solution is to help this web-based maintenance mode scheduler integrate better within SCOM. The solution contains 2 management pack files. The following items are included:

Class definitions and discoveries for the SCOM 2012 Maintenance Mode Scheduler.

The monitoring MP defines 2 classes. a Microsoft.Windows.ComputerRole based class called “SCOM 2012 Maintenance Mode Scheduler”, which has many properties defined representing various application settings.


There is also an unhosted class called “SCOM 2012 Maintenance Mode Scheduler Event Collector”. This class runs an event collection rule which collects the new schedule jobs creation events even when the Maintenance Mode Scheduler computer is in maintenance mode.

Automatically delete any finished maintenance mode schedules

A rule runs once a day and executes a script to scan through all Windows Scheduled Tasks created by the maintenance mode scheduler and deletes any tasks that does not have a Next Run Time (i.e. tasks that only runs once and it has already be executed). For auditing purposes, when deleting each old (finished) task, an event is also written to both SCOM operational and Data Warehouse databases.

The purpose of this rule is to eliminate the needs for manual clean-up of old scheduled tasks created by the maintenance mode scheduler.

Event Collection rule for new schedule job creation events (Event ID 711)

When the Maintenance Mode Scheduler is configure to write auditing events to Windows event log, a event collection rule can be utilized to collect these events and store them in SCOM databases.

image image

Monitor the credential of SCOM Data Access Account configured in the maintenance mode scheduler.

A monitor that checks if the credential of the SCOM Data Access Account configured in SCOM 2012 Maintenance Mode Scheduler is still valid. This is to ensure SCOM operators get notified if the Data Access account password has been changed, or the account has been locked out, disabled or deleted.

Monitor if the SCOM Data Access Account has local administrator privilege on the computer hosting the maintenance mode scheduler.

A monitor that checks if the SCOM Data Access Account configured in SCOM 2012 Maintenance Mode Scheduler has local administrator privilege on the computer hosting the scheduler. Windows local administrator access is required to create Windows Scheduled task.

Console task to launch the SCOM 2012 Maintenance Mode Scheduler web site using the default web browser.


New scheduler jobs event report


Maintenance Mode Scheduler dashboard (Provided by the SCOM 2012 Maintenance Mode Scheduler Dashboard management pack).


This dashboard contains:

  • Maintenance Mode Scheduler state widget
  • PowerShell Grid widget that lists new schedule jobs events
  • PowerShell Web Browser widget that displays the Maintenance Mode Scheduler web page.

Maintenance Mode Scheduler State view


New Jobs Event View


Deleted Jobs Event view



I’d like to thank Tim McFadden for producing such a good maintenance mode tool for SCOM 2012, and also the valuable feedbacks and suggestions provided for this management pack.


For me, while I was writing this MP, I’ve accomplished few of my “firsts”:

  • First time writing scripts for IIS (as this is a web based application).
  • First time writing reports in VSAE (I have to say for me, it is much easier than using old Authoring console)
  • First time using the new PowerShell widgets from the SCOM 2012 R2 UR2 updates (well, they’ve only just come out).

So I was really enjoying it, although it took a lot longer than what I expected (due to the IIS scripting challenges I had).

I hope this management pack would help the community to better adopt and integrate the SCOM 2012 Maintenance Mode Scheduler into their SCOM 2012 environments.

The Management packs and documentation can be downloaded HERE. Please make sure you read the documentation before importing the MPs. there are few pre-requisites for the MPs.

Lastly, as always, please feel free to contact me if you have issues / questions / suggestions.

System.Management.Automation.IncompleteParseException for a PowerShell script from my Management Pack

Written by Tao Yang

I’m currently working on a management pack that I’m hoping to be released to public very soon. In one of the workflows in the MP, I got an error logged in the Operations Manager event log on the target agent:

The PowerShell script failed with below exception

System.Management.Automation.IncompleteParseException: Missing closing ‘}’ in statement block.
at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
at Microsoft.EnterpriseManagement.Common.PowerShell.RunspaceController.RunScript[T](String scriptName, String scriptBody, Dictionary`2 parameters, Object[] constructorArgs, IScriptDebug iScriptDebug, Boolean bSerializeOutput)


Needless to say, the script runs just fine manually on the agent, so it is bug free. Took me a while to day to figure out what the issue is.

The script ended like this:


The last line is commented out, I’d uncomment it when test run it in powerShell prompt on an agent. When the MP is built in VSAE, it looked like this:


It’s on the same line as the CDATA close tag. After I started a new line at the end of the script, the MP started working:



From now on, I’ll remember to end the PowerShell script with an empty line. Interestingly, another VBScript in the MP doesn’t have this issue…

VMware Windows Guest Management Pack

Written by Tao Yang

This Monday, I was configuring monitoring for all our System Center 2012 servers as per our Windows support team’s requirement. Since all the virtual machines for our System Center 2012 servers are hosted on VMware ESX, they want to monitor the VMware Tools service on these guest VM’s. Since it was Monday morning and I had one bottle of wine the night before, I thought instead of write it myself, I’ll see if I can find a MP for this from the community so my brain can have a bit of rest. Unfortunately, I didn’t have too much luck as I couldn’t find a free and simple MP just to monitor the VMware guest VM’s 🙁

So I spent some time this week and quickly wrote a very simple management pack to monitor VMware Tools. Below is what’s included in this MP:

Class definitions:

  • VMware Guest Windows Computer Role
    • Based on Microsoft.Windows.ComputerRole


  • VMware Tools
    • Based on Microsoft Windows.ApplicationComponent
    • Hosted by VMware Guest Windows Computer Role


Discoveries for above mentioned classes


  • Basic Service monitor for VMware Tools service
    • Target: VMware Tools
  • VMware Tools Installation Status Monitor – A monitor to monitor if VMware Tools is installed
    • Target: VMware Guest Windows Computer Role
  • Dependency monitors to rollup VMware Tools health to it’s hosting class “VMware Guest Windows Computer Role”.


This MP is written using OpsMgr 2007 MP schema so it should work on both 2007 and 2012 versions. It can be downloaded HERE.

Since it’s a pretty simple MP, I didn’t bother to spend time writing a documentation. If you have questions or issues, please feel free to contact me.

Discovery for MS Clusters of Any Kind

Written by Tao Yang

Often when developing an OpsMgr management pack for server class applications, we need to be cluster-aware. Sometimes workflows don’t need to run on a cluster, sometimes, the workflow should only be executed on a cluster. (i.e. I wrote a monitor that runs on a Windows 2008 R2 Hyper-V cluster once a day and check if all virtual machines are hosted by their preferred cluster nodes.)

There are many good articles out there explaining cluster-aware discoveries in OpsMgr management packs:

However, in many occasions, only using the “IsVirtualNode” property from the Windows Server class (Microsoft.Windows.Server.Computer) is not enough (or granular enough) to identify the specific clusters.

I’m explain what I mean using an example.

For example, I have a 2-node SQL cluster configured as below:

  • Node 1 name: blablablaSQL01A
  • Node 2 name: blablablaSQL01B
  • Cluster Name: blablablaSQL01C
  • DTC Cluster Resource Access Name: blablablaSQL01D
  • SQL Server Cluster Resource Access Name: blablablaSQL01E


After installing the OpsMgr agent on both cluster nodes and enabled Agent-Proxy for them, totally 5 Windows Server objects will be discovered, one for each name mentioned above:


As shown above, other than the 2 cluster nodes, other 3 instances have “IsVirtualNode” property set to “True”.

When I looked at the “Computer” state view in the Microsoft SQL management pack, all 5 “Windows Server” are listed as the computer which has SQL installed:


If I create a discovery for SQL Clusters based on any computers have SQL DB Engine installed and is a virtual node, I would have discovered 3 instances (SQL01C, SQL01D and SQL 01E) for the same cluster.

If I only want to discover the cluster itself (blablablaSQL01C), I believe the discovery needs to perform the following checks:

01. The Windows Server Is Virtual Node

After a bit of digging, I found the “Windows Clustering Discovery” from Windows Cluster Library MP sets “IsVirtualNode” to True:


02. The existence of Cluster Service

I’m not sure if there are any management packs other than Windows Clustering Library out there that set IsVirtualNode to True. So , to be safe, I would also configure my discovery to look for the Cluster service.

03. The cluster is actually hosting my application

This is done via a WMI query to the MSCluster_Resource class in root\MSCluster name space.

In order to identify the cluster is hosting my application, I need to find if there are any cluster resources that has a specific resource type and also has a name that matches my search string.

i.e. I have access to 3 kinds of clusters in my work environment. I’ll list the WMI query for each cluster type:

SQL Cluster: “Select * from MSCluster_Resource Where Type = ‘SQL Server’ And Name LIKE ‘SQL Server’

Hyper-V Cluster: “Select * from MSCluster_Resource Where Type = ‘Virtual Machine’ And Name LIKE ‘Virtual Machine %’”

  • Note: This is because each VM in Hyper-V cluster have a resource name of “Virtual Machine <VM Name>”.

OpsMgr 2007 RMS Cluster: “Select * from MSCluster_Resource Where Type = ‘Generic Service’ And Name LIKE ‘System Center Data Access

As you can see, I believe in order to accurately identify my application, both cluster resource type and name need to match. Only using resource type in WMI query is not enough because the resource type could be “Generic Service”.

04. The computer name matches the cluster name

Because I am only interested in the actual cluster, not client access names for cluster resource groups, the computer name of the Windows Server instance needs to match the cluster name. I can read the cluster name in registry “HKLM\SYSTEM\CurrentControlSet\Services\ClusSvc\Parameters\ClusterName

In my sample MP, I created a class based on Microsoft.Windows.ComputerRole for my cluster and created a Timed Script Discovery based on the 4 criteria mentioned above.

Note: I know that using a script discovery targeting a wide range (all windows servers) is not ideal. I couldn’t manage to write a custom discovery module that meets my requirements. for example, the computer name could be in capital but the cluster name could be in lower case, System.ExpressionFilter (which is used by filtered registry discovery module) does not support case insensitive regular expression match (More Info). Therefore in my script, I have many IF statements nested. for example, if the windows server is not a virtual node, at the first if statement, it would not meet the if criteria and bypass the rest of the script, jump to the end of the script and submit an empty set of discovery data. I’ve done it this way to ensure the script does not continue running if one criteria is not met.

Again, using SQL clusters as an example, I created a class called “SQL Server Cluster”, and only the actual clusters (name ends with letter “C”) are discovered:


In order to re-use the code, I have create a snippet template in VSAE. This snippet template includes the class definition, discovery workflow and associated language pack (ENU) display strings.

Here’s the code for the snippet template:

<ManagementPackFragment SchemaVersion="1.0">
 <ClassType ID="#text('MP Id')#.#text('Cluster Type')#.Cluster.ComputerRole" Base="#alias('Microsoft.Windows.Library')#!Microsoft.Windows.ComputerRole" Accessibility="Public" Abstract="false" Hosted="true" Singleton="false">
 <Property ID="ClusterName" Key="false" Type="string" />
 <Discovery ID="#text('MP Id')#.#text('Cluster Type')#.Cluster.ComputerRole.Discovery" Target="#alias('Microsoft.Windows.Library')#!Microsoft.Windows.Server.Computer" Enabled="true" ConfirmDelivery="false" Remotable="true" Priority="Normal">
 <DiscoveryClass TypeID="#text('MP Id')#.#text('Cluster Type')#.Cluster.ComputerRole">
 <Property TypeID="#text('MP Id')#.#text('Cluster Type')#.Cluster.ComputerRole" PropertyID="ClusterName" />
 <DataSource ID="DS" TypeID="#alias('Microsoft.Windows.Library')#!Microsoft.Windows.TimedScript.DiscoveryProvider">
 <SyncTime />
 <Arguments>$MPElement$ $Target/Id$ $Target/Property[Type="#alias('Microsoft.Windows.Library')#!Microsoft.Windows.Computer"]/PrincipalName$ "#text('Cluster Resource Type')#" "#text('Cluster Resource Name Search String')#" "$Target/Property[Type="#alias('Microsoft.Windows.Library')#!Microsoft.Windows.Server.Computer"]/IsVirtualNode$"</Arguments>
' AUTHOR: Tao Yang
' Script Name: ClusterDiscovery.vbs
' DATE: 20/03/2014
' Version: 1.0
' COMMENT: Script to discover failover clusters
On Error Resume Next
SourceID = WScript.Arguments(0)
ManagedEntityID = WScript.Arguments(1)
strComputer = WScript.Arguments(2)
strCLResType = WScript.Arguments(3)
strCLResName = WScript.Arguments(4)
'IsVirtualNode property from Windows.Server.Computer class is either true or empty. never false
IF NOT IsNull(WScript.Arguments(5)) THEN
bIsVirtualNode = WScript.Arguments(5)

'Declare variables
const HKEY_LOCAL_MACHINE = &H80000002

Set oAPI = CreateObject("MOM.ScriptAPI")
Set oDiscoveryData = oAPI.CreateDiscoveryData(0,SourceID,ManagedEntityID)

'Only continue if IsVirtualNode = "True"
IF UCase(bIsVirtualNode) = "TRUE" Then
 'Check if Failover Cluster service exists
 strKeyPath = "SYSTEM\CurrentControlSet\Services\ClusSvc"
 'connect to the registry provider
 Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
 If oReg.EnumKey(HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys) = 0 Then
 'Cluster Service exists, continue, check if specified cluster resource exists
 bCLRes = False
 CLResWMIQuery = "Select * from MSCluster_Resource Where Type = '" & strCLResType &"' AND Name LIKE '" & strCLResName & "'"
 Set objWMICluster = GetObject("winmgmts:\\" & strComputer & "\root\MSCluster")
 Set ColCLRes = objWMICluster.ExecQuery (CLResWMIQuery)
 For Each objCLRes in ColCLRes
 bCLRes = TRUE

'NetBIOS Computer Name
 ComputerName = Split(strComputer, ".", -1)(0)
 'Read Cluster name from registry
 strCLKeyPath = "SYSTEM\CurrentControlSet\Services\ClusSvc\Parameters"
 strCLNameValue = "ClusterName"
 oReg.GetStringValue HKEY_LOCAL_MACHINE,strCLKeyPath, strCLNameValue,strClusterName

'Proceed if NetBIOS Computer Name equals to cluster name
 If UCase(ComputerName) = UCase(strClusterName) Then
 Set oInstance = oDiscoveryData.CreateClassInstance("$MPElement[Name='#text('MP Id')#.#text('Cluster Type')#.Cluster.ComputerRole']$")
 oInstance.AddProperty "$MPElement[Name='#alias('Microsoft.Windows.Library')#!Microsoft.Windows.Computer']/PrincipalName$", strComputer
 oInstance.AddProperty "$MPElement[Name='System!System.Entity']/DisplayName$", strComputer
 oInstance.AddProperty "$MPElement[Name='#text('MP Id')#.#text('Cluster Type')#.Cluster.ComputerRole']/ClusterName$", UCase(strClusterName)
 End If
oAPI.Return oDiscoveryData
 <LanguagePack ID="ENU" IsDefault="true">
 <DisplayString ElementID="#text('MP Id')#.#text('Cluster Type')#.Cluster.ComputerRole">
 <Name>#text('Class DisplayName')#</Name>
 <DisplayString ElementID="#text('MP Id')#.#text('Cluster Type')#.Cluster.ComputerRole" SubElementID="ClusterName">
 <Name>Cluster Name</Name>
 <DisplayString ElementID="#text('MP Id')#.#text('Cluster Type')#.Cluster.ComputerRole.Discovery">
 <Name>#text('Class DisplayName')# Discovery</Name>
 <Description>Script discovery for #text('Class DisplayName')#</Description>

When using this template, for each cluster that you want to define and discover in your MP, simply supply the following information:


  • MP Id: the ID (or the prefix) of your MP. this is going to be used as the prefix for all the items defined in the snippet.
  • Cluster Type: the type (or common name) of your cluster. i.e. SQL, Hyper-V, etc.
  • Cluster Resource Type: The value of the “Type” property of the MSCluster_Resource WMI instance.


  • Cluster Resource Name Search String: the search string for the cluster resource name.


The “SQL Server Cluster” discovered in the previous screenshot is created using this snippet template.

You can also download the snippet template here.

Discoveries in Fujitsu PRIMERGY Server Management Pack

Written by Tao Yang

I have been dealing this the Fujitsu PRIMERGY Server MP from Fujitsu ever since I started working for my current employer about 2.5 years ago. We found many issues with the previous version back in SCOM 2007 days and now as I’m setting up SCOM 2012 R2 management groups and having to implement the latest version, I believe there are still lots of rooms for improvement. I’ll only discuss discoveries in this blog article.

Other than the group populators, there is only one discovery workflow that discovers PRIMERGY servers as well as all other server components. This discovery runs a long VBScript (I counted, it has 5798 lines of code) on all Windows Server computers, every 1 hour by default. It breaks almost all the MP discovery best practices that I can think of.


Discoveries are not staged

The MP should have included a simple top level registry based discovery to discover if the server is a Fujitsu server and then target all subsequent discoveries to the Fujitsu server that’s been discovered by the top level registry discovery.

Target is too generic

Targeting a script discovery to all server computers is a bad idea. nowadays, in most of environments, there are more virtual servers than physical servers. Why would I want to run this discovery to discover Fujitsu servers AS WELL AS all other server components on my virtual servers when clearly they are not going to be a Fujitsu server?

Single discovery for multiple classes

As you can see from the screenshot above, the discovery discovers 14 items. This has made impossible to disable discovery for any individual components.

In the previous version of MP (version 4), the script also discovers the actual temperature from various temperature sensors. I’m not sure why these data is required to be stored as properties of the server and it is a bad idea because it’s very unlikely that the temperature stays the same over a long period of time (i.e. 28.1 degrees now and 28.2 degrees an hour later). This has caused us a big issue when we realised few thousands Fujitsu servers were resubmitting discovery data every hour (config churn) in our SCOM 2007 environments. We couldn’t do anything about it if we want to keep the integrity of the vendor supported MP, because we can’t just disable the discovery for this particular component without actually modifying the VBScript in the discovery data source. In the end, we had to get Fujitsu to update script in the MP and seal it with their key to get around this issue.

In the current version (version 6), looks like they’ve kept this modification in the script:


Script based discovery runs too frequent (once an hour)

According to Microsoft’s best practise, script discoveries should have a minimum interval of 4 hours (and should not target a broad class). Not to mention the script for this discovery is almost 6000 lines long!

In order to overcome these issues, I have created an additional addendum MP. Below is a list of what I’ve done in this addendum MP:

1. Created a custom class called “Fujitsu Server Computer (Addendum MP)”.

2. Create a registry based discovery for the “Fujitsu Server Computer (Addendum MP)”. This discovery is based on “HKLM\System\CurrentControlSet\Control\SystemInformation\SystemManufacturer” regkey value.


3. Created a group for all instances of “Fujitsu Server Computer (Addendum MP)” class.

4. Created an override to disable the original discovery from Fujitsu MP ( called “PRIMERGY Server Discovery Rule”).

5. Created an override to enable the original discovery for the group I created in the previous step.

6. Created an override to change the interval from 3600 seconds (1 hour) to 43200 seconds (12 hours).

This addendum MP can be downloaded HERE. I recommend anyone who’s using the Fujitsu PRIMERGY Server MP to take a look.

Lastly, the intention of this blog post is not to criticise Fujitsu, but rather making effort to make this MP better. Honestly, based on my own experience, Fujitsu has been pretty good listening to their customers and I am happy that they have rolled up the temperature sensor discovery changes to the new MP.

ConfigMgr 2012 (R2) Clients Management Pack Released

Written by Tao Yang

ConfigMgr 2012 Client MP IconTime flies, I can’t believe it’s been over 7 months since I posted the beta version of the ConfigMgr 2012 client MP for testing. I haven’t forgotten about this MP (because it’s one of the deliverables for the System Center 2012 upgrade project that I’ve been working on for the last 12 months or so). Today, I finally managed to finish updating this MP, it is ready for final release (Version

I didn’t manage to get many feedbacks since the beta version was released. so it’s either a good thing that everyone’s happy about it, or it’s really bad that no one bothered to use it 🙂 . I would hope it’s because that everyone’s happy about it 🙂

Anyways, below is a list of what’s changed.

Display Name for the ConfigMgr 2012 Client Agents are changed.

in beta version, the display names various client agents(DCM agents, Hardware Inventory agents, etc.) were hardcoded to the client agent name:


I don’t believe it is too user friendly when working in the Operations Console, so in this version, I’ve changed them to be the actual computer name:


Bug Fix: Incorrect Member Monitors for various client agents dependency monitors.

I made a mistake when writing the client agents dependency monitor’s snippet template in VSAE. As the result, all dependency monitors (for availability, performance, configuration and security health) had client agents availability health aggregate monitors as member monitors.


This is now fixed. the correct member monitor is assigned to each dependency monitor.


ConfigMgr 2012 Client object is no longer discovered on cluster instances.

When I was working on the beta version, the development management group that I was using did not have any failover clusters. I didn’t realise the ConfigMgr 2012 Client object is being discovered on cluster instances (virtual nodes) until I imported the MPs into our proper test environment. So this is something that has been overlooked. It is fixed now, it will not discover ConfigMgr 2012 Client (and any client agents) on clusters.

The “ConfigMgr 2012 Client All Programs Service Window Monitor” is now disabled by default.

I’m not too sure how many environments will have a maintenance window (service window) created for all clients. Therefore I’ve disabled this monitor. this is to ensure it will not flood SCOM by generating an alert for each ConfigMgr client. If it is required for all or a subset of ConfigMgr clients, it can be enabled via overrides.

Few spelling mistakes in alerts descriptions are corrected.

Finally, since the beta version was released prior to System Center 2012 R2 release, I have also tested the this MP on ConfigMgr 2012 R2 environment, it is 100% compatible without any modifications.

It can be downloaded HERE. As always, please feel free to contact me if you have any issues or suggestions.

12th April, 2014 Update: Stanislav Zhelyazkov found the override MP packed in the zip file is not correct. It did not have any references to other sealed MP. Not sure what happened when I preparing the zip file. Anyways, If you intend to use the unsealed override MP, please use this one instead.

OpsMgr 2012 Self Maintenance Management Pack Update (Version

Written by Tao Yang

I have been extremely busy lately. Although I had few new ideas for the OpsMgr 2012 Self Maintenance MP for a while, I couldn’t find time to update it. This weekend, I managed to find some spare time and updated this management pack.

What’s new?

Updated the Close Aged Rule Generated Alerts Rule

Awhile back, someone suggested me to add a comment to the alert when it’s being closed by this rule. I think it’s a good idea, so I’ve updated this rule. now any alerts closed by this rule will have a comment “Closed by OpsMgr 2012 Self Maintenance Management Pack”:


New Agent Task: Get Management Groups configured on an agent

This new task is targeting the agent class, it displays the management groups that are configured on the OpsMgr 2012 agents:


Note: Since there is already a state view for agents built-in in OpsMgr 2012, I did not bother to create such a view in this management pack. You can find the “Agents By Version” state view under Operations Manager\Agent Details:


New Rule: Auto approve manually installed agents if their computer names and domain names match configurable regular expressions

By default in OpsMgr, there are 3 possible options for manually installed agents:

  • Reject all
  • Automatically Approve all
  • Manually Approve by OpsMgr administrators

The “OpsMgr 2012 Self Maintenance Approve Manual Agents Rule” runs on a schedule and approve manually installed agents of which computer name and domain name match the configurable computer name and domain name regular expression. This rule presents 2 benefits:

1. Allow OpsMgr to automatically approve agents based on preconfigured naming convention. It eliminates the needs for administrators to manually approve agents.

2. Agents approvals are staged. This prevents large number of agents are approved at once. In a large OpsMgr environment, this is particularly important as approving a large number of agents at once could consume a lot of system resources on management servers to transfer management packs and process the initial discovery workflows submitted from the agents.

This rule can be customized using overrides:

  • IntervalMinutes: How often (in minutes) does this rule run.
  • AgentNameRegex: Regular Expression for acceptable Agent computer names
  • AgentDomainRegex: Regular Expression for acceptable Agent domain names
  • MaxToApprove: Maxinum number of manually installed agents to be approved at a time.
  • SyncTime: What time does this rule run.
  • TimeoutSeconds: Timeout in seconds for the PowerShell script inside the rule.

This rule will approve manually installed agents (up to the number configured for MaxToAPprove) if both agent’s computer name and domain name match configured regular expressions.

An information alert is generated if the rule has approved at least one (1) agent(s).


The list of approved agents is shown in Alert Context:


As shown in above alert, in my lab, I have configured the rule to approve any agents that have “CLIENT” as part of the computer name and the the domain name is exactly “corp.tyang.org”. It found 2 agents pending approval, since MaxToApprove value is set to 2, both agents are approved.

Note: the rule uses case insensitive match (PowerShell –imatch operator). If you need help with building your regular expression, this article is a good starting point:

PowerShell: Working With Regular Expressions (regex)

I wrote this rule for the upcoming OpsMgr agents migration at work. As part of the System Center 2012 upgrade project that I have been working on over the last year or so, we will be migrating around 30,000 agents from 2 OpsMgr 2007 R2 management groups to 3 OpsMgr 2012 R2 management groups. I still remember the pain we have gone through couple of years ago when we added over 20,000 desktop computers into OpsMgr 2007 R2. at that time, to save us time manually approve these agents, I temporarily made the configuration change to allow OpsMgr to auto approve all manual agents. Although we have staged the agent rollout in ConfigMgr, we still had issues in OpsMgr as the management servers just couldn’t keep up with the load and most of the agents where showing Not Monitored with a green circle even days after been added to the management group.

So I would think this rule is like the bouncer standing in front of the night club. it will only allow someone you like to come in, and it also controls how many you will let in at once (so the night club don’t get too crowded). It will also make sure agents don’t get added to the wrong management group when there are multiple management groups in the environment.

I would also use this rule in conjunction with the auto balancing management servers rule from the same management pack, so after the agents are approved, they are balanced across multiple management servers.

New Monitor: Detect if each individual management server is in maintenance mode

This new monitor is called “OpsMgr 2012 Self Maintenance Local Management Server in Maintenance Mode Monitor”. Previously, I wrote another monitor in this MP called “OpsMgr 2012 Self Maintenance Management Servers in Maintenance Mode Monitor”.

Writing a workflow to detecting if someone is in maintenance mode could be tricky in OpsMgr. because if you are in maintenance mode, you would unload all workflows and therefore it would not run the maintenance mode detection workflow. This is why when I wrote the original monitor, I targeted the monitor to run on “All Management Servers Resource Pool”. However, it has a limitation that it will only generate alerts when more than 50% of members of “All Management Servers Resource Pool” is healthy and not in maintenance mode.

With the new monitor, I was inspirited by Kevin Holman’s recent blog article How to create workflows that wont go into Maintenance Mode (Thanks Kevin!). As Kevin explained in his blog article, in order to make this monitor to run on each individual management server and continues to run even when its Windows Computer object has been placed into maintenance mode, I have created an unhosted class called “OpsMgr 2012 Self Maintenance Management Server Maintenance Mode Watcher”. This object is discovered on each management server and it is not hosted by the Windows Computer. By doing so, this monitor will continue to run even when the management server’s Windows Computer object has been placed into maintenance mode.

A recovery task is also associated to this monitor (disabled by default). When enabled, it will automatically end the maintenance mode for the management server.

As the standard for the Self Maintenance MP, all workflows are disabled by default. Therefore, the object discovery for the Maintenance Mode Watcher class, this monitor itself and associated recovery task are all disabled by default.

Note: In order to utilise this monitor, the object discovery and the monitor itself will need to be enabled via overrides. Optionally, the recovery task can also be enabled if you want the monitor to automatically end the maintenance mode for the management servers.

Object Discovery:




Recovery Task:


Note: I purposely did not create a state view for the Maintenance Mode Watcher objects. I don’t want normal operators to see these objects (so they can place the watcher objects into maintenance mode directly).

When I placed All 3 management servers in my lab into maintenance mode:


The maintenance mode watcher objects became unhealthy:


An alert was generated for each management server:


From the screenshot above, you can see that other alerts were generated for various resource pools heartbeat failures because all management servers are in maintenance mode. In this scenario, the old monitor that targets the “All Management Servers Resource Pool” would not work.

When I enabled the recovery task, the management server has been taken out of maintenance mode automatically:


As shown in above screenshot, I placed a management server into maintenance mode for 30 minutes (as shown in the MaintModeDetails), because I configured the monitor to run every 1 minute, on 11:57PM local time, (within 1 minute of the maintenance mode start time), the monitor detected the management server was in maintenance mode, and the recovery task has ended the maintenance mode.

Note: Please enable this recovery task with caution. i.e. If the monitor is configured to run every 5 minutes, you will never be able to place a management server into maintenance mode for more than 5 minutes. It may not always be desired.

The updated MP and documentation can be downloaded HERE.

As always, please feel free to contact me if you have any feedbacks.