Using PowerShell to Check for Syntax Errors in System.ExpressionFilter Modules (OpsMgr Authoring)

With its wide range of usefulness in implementing conditional logic, expression evaluation, and error filtering, the System.ExpressionFilter module is likely to be a frequently used module in most OpsMgr Management Pack authoring scenarios.   However, the default configuration for the System.ExpressionFilter module may lead to a potential syntax error that is quite easy to miss, in my opinion.  This potential syntax error relates to the default configuration of the ValueExpression elements of the ExpressionFilter, in that the ValueExpression defaults to an XPathQuery value type.   If this default is not changed when evaluating a non-XPathQuery value, the workflow (as well as all workflows cooked down with the faulted workflow) will fail.

To illustrate an oversight resulting in this error, the following ExpressionFilter configuration would result in a workflow failure:

<SimpleExpression>
   <ValueExpression>
        <XPathQuery>ErrorCode</XPathQuery>
   </ValueExpression>
   <Operator>Equal</Operator>
   <ValueExpression>
       <XPathQuery>1</XPathQuery>
    </ValueExpression>
</SimpleExpression>

The correct implementation of this Expression Filter module would be:

<SimpleExpression>
   <ValueExpression>
        <XPathQuery>ErrorCode</XPathQuery>
   </ValueExpression>
   <Operator>Equal</Operator>
   <ValueExpression>
       <Value>1</Value>
    </ValueExpression>
</SimpleExpression>

Unfortunately, this type of error is not caught by the MPBPA, most likely due to the difficulty in differentiating between a valid XPathQuery value and string value.  To perform some basic error checking to identify these errors when authoring, I have written a simple PowerShell script that analyzes the XML of an unsealed Management Pack and reports errors and potential errors with ValueExpression configuration in ExpressionFilter modules.  

The logic of the script assumes the following:

  • Any ValueExpression configured as an XPathQuery expression and having a value that starts with a dollar sign ($) can be assumed to be a configuration error
  • Any ValueExpression configured as an XPathQuery expression and having a value that does not start with a forward slash or the strings:  Property or ErrorCode might be misconfigured

The script accepts the path to the Management Pack XML file as the single input parameter and then searches the XML for RegExExpression, SimpleExpression, and DayTimeExpression XML nodes.  These nodes are evaluated for mismatches on XPathQuery expressions and mismatches are reported to the console.

The output of the script looks like:

PS D:\Development\SCOM> ./checkexpressionfilters.ps1 -MPFIle:”d:\development\scom\xsnmp\1.1.Dev\xSNMP.AIX.xml”
Evaluating d:\development\scom\xsnmp\1.1.Dev\xSNMP.AIX.xml 

Error – Found mismatched XPathQuery value with XML:
<XPathQuery>$Target/Property[Type=”xSNMP.AIX.Processor”]/Name$</XPathQuery> 

Error – Found mismatched XPathQuery value with XML:
<XPathQuery>$Target/Property[Type=”xSNMP.AIX.Processor”]/Name$</XPathQuery> 

Errors found: 2
Warnings found: 0

The script can be downloaded here.

The body of the script is:

Param([string]$MPFile)

[xml]$XMLData = Get-Content $MPFile
write-host “Evaluating $MPFile”
write-host  “”
 
$ErrorCount=0
$WarningCount=0
$Nodes = $XMLData.SelectNodes(“//RegExExpression”)
$Nodes| ForEach-Object{
 $XPathExpressions = $_.SelectNodes(“.//XPathQuery”)
 $XPathExpressions | ForEach-Object{
  $ExpressionText = $_.InnerText
  if([string]$ExpressionText.Substring(0,1) -eq [string]”$”){
   [String]$OuterXML = $_.OuterXML
   $ErrorCount += 1
   $sMesg = “Error – Found mismatched XPathQuery value with XML: ” `
   + [environment]::NewLine + $OuterXML + [environment]::NewLine
   write-host $sMesg
  }
  
  if(($ExpressionText.Substring(0,1) -ne “/”) `
   -and ($ExpressionText.Substring(0,8) -ne “Property”) `
   -and ($ExpressionText.Substring(0,1) -ne “$”) `
   -and ($ExpressionText.Substring(0,9) -ne “ErrorCode”)){
   [String]$OuterXML = $_.OuterXML
   $WarningCount += 1
   $sMesg = “Warning – Found mismatched XPathQuery value with XML: ” `
   + [environment]::NewLine + $OuterXML + [environment]::NewLine
   write-host $sMesg
  }
 }
}

$Nodes = $XMLData.SelectNodes(“//SimpleExpression”)
$Nodes| ForEach-Object{
 $XPathExpressions = $_.SelectNodes(“.//XPathQuery”)
 $XPathExpressions | ForEach-Object{
  $ExpressionText = $_.InnerText
  if([string]$ExpressionText.Substring(0,1) -eq [string]”$”){
   [String]$OuterXML = $_.OuterXML
   $ErrorCount += 1
   $sMesg = “Error – Found mismatched XPathQuery value with XML: ” `
   + [environment]::NewLine + $OuterXML + [environment]::NewLine
   write-host $sMesg
  }
  
  if(($ExpressionText.Substring(0,1) -ne “/”) `
   -and ($ExpressionText.Substring(0,8) -ne “Property”) `
   -and ($ExpressionText.Substring(0,1) -ne “$”) `
   -and ($ExpressionText.Substring(0,9) -ne “ErrorCode”)){
   [String]$OuterXML = $_.OuterXML
   $WarningCount += 1
   $sMesg = “Warning – Found mismatched XPathQuery value with XML: ” `
   + [environment]::NewLine + $OuterXML + [environment]::NewLine
   write-host $sMesg
  }
 }
}

$Nodes = $XMLData.SelectNodes(“//DayTimeExpression”)
$Nodes| ForEach-Object{
 $XPathExpressions = $_.SelectNodes(“.//XPathQuery”)
 $XPathExpressions | ForEach-Object{
  $ExpressionText = $_.InnerText
  if([string]$ExpressionText.Substring(0,1) -eq [string]”$”){
   [String]$OuterXML = $_.OuterXML
   $ErrorCount += 1
   $sMesg = “Error – Found mismatched XPathQuery value with XML: ” `
   + [environment]::NewLine + $OuterXML + [environment]::NewLine
   write-host $sMesg
  }
  
  if(($ExpressionText.Substring(0,1) -ne “/”) `
   -and ($ExpressionText.Substring(0,8) -ne “Property”) `
   -and ($ExpressionText.Substring(0,1) -ne “$”) `
   -and ($ExpressionText.Substring(0,9) -ne “ErrorCode”)){
   [String]$OuterXML = $_.OuterXML
   $WarningCount += 1
   $sMesg = “Warning – Found mismatched XPathQuery value with XML: ” `
   + [environment]::NewLine + $OuterXML + [environment]::NewLine
   write-host $sMesg
  }
 }
}
Write-Host “Errors found: $ErrorCount”
Write-Host “Warnings found: $WarningCount”

Advertisement

About Kristopher Bash
Kris is a Senior Program Manager at Microsoft, working on UNIX and Linux management features in Microsoft System Center. Prior to joining Microsoft, Kris worked in systems management, server administration, and IT operations for nearly 15 years.

One Response to Using PowerShell to Check for Syntax Errors in System.ExpressionFilter Modules (OpsMgr Authoring)

  1. Jonathan Almquist says:

    Thanks, Kristopher. This will probably come in handy in some. Keep up the excellent work. You’re providing the community with much value.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: