Using PowerShell to Check for Syntax Errors in System.ExpressionFilter Modules (OpsMgr Authoring)
July 17, 2010 1 Comment
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.xmlError – 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”
Thanks, Kristopher. This will probably come in handy in some. Keep up the excellent work. You’re providing the community with much value.