# .\Matthew Long

## The SCOM Unsung Hero – Using the System.ExpressionFilter Module

Posted by Matthew on July 3, 2012

I’ve decided to write a blogpost as tribute to the unsung hero of Operations Manager, the one module that gets used in virtually every workflow but is rarely the focus of attention.  Without this module cookdown would be mostly impossible and whether you are creating your own modules or using the Wizards in the SCOM console/ Authoring Console / Visio Extension, it’s always there to assist you.  I’m talking of course about the System.ExpressionFilter.

## What is it?

The System.ExpressionFilter is a condition detection module and sibling to the System.LogicalSet.ExpressionFilter.  It’s function is to examine items in the operations manager workflow and either pass them on or remove (drop) them from the workflow.  If no items matched the filter at all, the workflow terminates.

In only has a single configuration parameter, but it’s a very powerful one, as it accepts the ExpressionType configuration.  In reality most of this article will be talking about the syntax of ExpressionType.

It’s also a very lightweight module, and should be used whenever you need to do any kind of determination or filtering.  Whenever you are using a service monitor, event log reader, SNMP probe, the parameters you are filling in are nearly all being sent to this module not the data source!

## When should you use it?

• 90% of the time, if you want to implement cookdown for your workflow, you’ll be using this module.
• You want to add further filtering onto an existing rule in an unsealed management pack.
• You want to perform filtering of any kind of data.
• You are implementing a MonitorType (not the same thing as a monitor)

## Configuration

The System.ExpressionFilter only takes a single parameter, of type ExpressionType.  This is an inbuilt data type in SCOM that allows you to specify some kind of evaluation criteria that operations manager will run on every item sent to the module.  It should be noted that each item will be evaluated individually (if you need to do them as a linked set, see the System.LogicalSet.ExpressionFilter).

Expression filters are very complex types.  They support nested expressions using the And and Or group constructions, and you also have access to NOT.  Below i’ll give you a sample of the type you are going to use 75% of the time..

### SimpleExpression – Compare output of PropertyBagScript to value

<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="String">Property[@Name='Status']</XPathQuery>
</ValueExpression>
<Operator>Equal</Operator>
<ValueExpression>
<Value Type="String">Healthy</Value>
</ValueExpression>
</SimpleExpression>
</Expression>


This is the most common filter you’ll use in SCOM. It’s purpose is to compare the output of a module (in this case, a PropertyBagScript value called “Status”) with a value. This can either be a static value, or one passed in to the workflow as part of a $Config/$ parameter.

We start off opening with an <Expression> tag, which is always the starting and end tag for each evaluation.  Then we’ve stated on line 2 that we want to use a SimpleExpression, which just does a straight comparison between two items (the first ValueExpression and Second ValueExpression).  The valid operators for use with a SimpleExpression are:

• Equal
• NotEqual
• Greater
• Less
• GreaterEqual
• LessEqual

Note that when specifying the operators they are case-sensitive, so they need to be entered exactly as above.  Finally our ValueExpressions (the left and right side of the comparison) are either of type Value or XPathQuery.  You use Value when using either static values or $Config/$ or $Target/$ parameters, and XPathQuery when you want to examine the output of the previous module.

Finally you’ll note that both Value and XPathQuery have a Type attribute – SCOM will attempt to cast the data into that type before performing the query.  So if you are comparing two numbers make sure you have the type set to Integer, otherwise it will attempt to calculate if the ‘letter’ 3 is greater than ’86’, which probably isn’t your intent.  The available types are:

• Boolean
• Integer
• UnsignedInteger
• Double
• Duration
• DateTime
• String

The SCOM 2007 Authoring console will by default always set the type to “String”, so keep an eye on that.  Also, if the type conversion fails, SCOM is going to throw an error into the event log and the item will not be processed.

### Logical Operators – And Or and NOT

You can group and reverse the result of expressions using the <And>, <Or> and <Not> expression elements.  How they are implemented is a wrapper for your <Expression></Expression> tag that themselves are expressions!  Sounds complicated, but with an example it becomes much clearer:

<Expression>
<And>
<Expression>
<!-- First expression here -->
</Expression>
<Expression>
<!-- Second expression here -->
</Expression>
</And>
</Expression>


So above we have two expressions that most both evaluate to true in order for the whole outer expression to be true.  The construct is the same for <Or> and <Not>, and you can even nest groups in groups for truly powerful expressions!  <Not> may only contain a single <Expression> (that of course, could be a group!), but <And> and <Or> can contain two or more expressions if you need to group on multiple items.

One important thing to note is that groups support short circuiting.  What this means is that if we examine one expression in an And/Or group and we can deduce from the first expression that the whole thing will be true or false (perhaps we are using And and the first item is False) then SCOM won’t bother to evaluate the second expression, saving time and performance.  So nest away!

### Exists – Does my data item contain a property?

Much like a type conversion failure, if an XPathQuery value (as part of a SimpleExpression) doesn’t resolve to anything, say because that data item doesn’t contain an expected property, then the Expression will fail and that item will be dropped.  So if you are dealing with a property that doesn’t always show up (regardless of if it has a value, SCOM can deal with empty/null properties) you’d be wise to use the <Exists> expression.  It’s also useful if you don’t care about the value of a property, merely if it exists or not.

<Expression>
<Exists>
<ValueExpression>
<XPathQuery Type="Integer">Params/Param[1]</XPathQuery>
</ValueExpression>
</Exists>
</Expression>


Here we are checking to see if an event log entry has at least 1 parameter.  You can also use <Value> instead of XPathQuery if you wanted to check to see if a $Config/$ parameter exists so you know if an optional parameter on your module has been specified or not.

If you need to check the result of a value that may or may not exist, you’ll want to take advantage of the short circuiting of thegroup by combining an exists check with your value check.  Make sure the exists expression is first in the group, and that way if the property doesn’t exist SCOM won’t bother trying to read the property (which, as stated above will cause the module to fail).  I’ve included an example of this below!

<Expression>
<And>
<Expression>
<Exists>
<ValueExpression>
<XPathQuery Type="Integer">Params/Param[1]</XPathQuery>
</ValueExpression>
</Exists>
</Expression>
<Expression>
<SimpleExpression>
<ValueExpression>
<XPathQuery Type="Integer">Params/Param[1]</XPathQuery>
</ValueExpression>
<Operator>Less</Operator>
<ValueExpression>
<Value Type="Integer">Params/Params[1]</Value>
</ValueExpression>
</SimpleExpression>
</Expression>
</And>
</Expression>


### Regular Expressions

If you want to do powerful (or simple!) regular expression comparisons, then the ExpressionFilter has got you covered.  I’m not going to go into a huge amount of depth on this one, because by now you should be getting an idea of how this works.  I’ll just show you the syntax and then list the regex pattern styles you can use.

<Expression>
<RegExExpression>
<ValueExpression>
<XPathQuery Type="String">EventPublisher</XPathQuery>
</ValueExpression>
<Operator>ContainsSubstring</Operator>
<Pattern>Microsoft</Pattern>
</RegExExpression>
</Expression>


ValueExpression is the same as with a SimpleExpression, so you can compare against incoming data items on the workflow or input parameters.  Operator allows you to specify what type of matching you’d like to perform:

• MatchesWildcard– Simple wildcard matching using the below wildcards
• # – Matches 0-9
• ?  – Any single character
• * – any sequence of characters
• \ – escapes any of the above
}
While (Test-Path $FilesLocation -ErrorAction SilentlyContinue)  For those unfamiliar, the Do..While construct will attempt an action once, and then check the criteria to see if the action should be repeated. In this case Test-Path will return true if the path exists and false if it does not. So if the folder has been deleted, another attempt will be made. The -ErrorAction SilentlyContinue parameters simply stop the commands from writing out either the error condition we are explicitly handling (files locked in use) or that the path does not exist (which is what we want in this scenario, so lets not raise an error for that state). ## Copy-Item This one has been around the internet a few times already, and in this case the solution was one I came across. Unfortunately I’m not sure who the original author is, but if anyone knows I’ll gladly accredit it. Anyway, the issue is that Copy-Item has a slight behavioural quirk; if you try to copy a folder, and the destination folder name already exists, the item(s) to be copied are instead placed inside the pre-existing destination folder, in a subfolder. The result is that if you tried to copy the contents of c:\foo to c:\bar, and bar already existed you’d wind up with all your files from c:\foo inside the c:\bar\bar folder! Thankfully, the function below sorts this behaviour out – Function Copy-Directory { Param( [System.String]$Source,
[System.String]$Destination)$Source = $Source -replace '\*$'
If (Test-Path $Destination) { Switch -regex ($Source)
{
'\\$' {$Source = "$Source*"; break} '\w$' {$Source = "$Source\*"; break}
Default {break}
}
}
Copy-Item $Source$Destination -recurse -force
}


Now you can call Copy-Directory folder1 folder2 and get consistent results – if the destination does not exist, it is created. If the destination does exist, then all files are copied into the pre-existing folder.

The function works by testing if the destination folder already exists, and if it does, modifying the source criteria so that copy-item is instead looking for a wildcard match on the folders contents, rather than the source folder itself.

## Scripting Series – Interesting things you can do with VBScript and Powershell Part 4 – Setting up HyperV host networking

Posted by Matthew on October 11, 2011

As you may recall from the introduction to this series, I was tasked with creating a script that would handle the setup/tear down of student lab machines that were to be used for short training courses.  The PCs belong to the training provider and it’s up to the instructor to come in before the course and set all of the student machines up.  Often 15 times, on a sunday.

This post deals with the (relatively simple) task of setting up the virtual network adapter that is normally nearly always provided as an internal/external network on the student machines, specifically the IP settings so that the guest VMs can communicate with the host HyperV server.

Let’s take a look at the script first, and then i’ll walk you through it.  As noted in the first article, I used James O’ Neill’s fantastic HyperV Module to accomplish the HyperV lifting!

## The Script


#Setup Internal HyperV Network if it doesn't already exist

If (!(Get-VMSwitch $NetworkName)) { New-VMInternalSwitch -VirtualSwitchName$NetworkName -Force | Out-Null
}
Else
{
Write-Host "nVirtual Network '$NetworkName' already exists, Skipping..." } #Setup Local Loopback adapter$vSwitch = Get-WmiObject -Query ('Select * from Win32_PnPEntity where name = "' + $NetworkName +'"')$Query = "Associators of {$vSwitch} where ResultClass=Win32_NetworkAdapter"$NicName = (Get-WmiObject -query $Query ).NetConnectionID Invoke-Expression 'netsh interface ip set address "$NicName" static 192.168.1.150 255.255.255.0'
Write-Host "Server now has IP on internal network of '192.168.1.150'"

`

The code is fairly self explanatory, but i’ll walk through it anyway.  First we use the HyperV module to determine if there is an Internal network with the given name in $NetworkName already in existence, and if not we create it. If you haven’t seen it before, Out-Null is a powershell command to send pipeline information into the aether, and is useful when you don’t want a cmdlet writing back objects or text to the console during execution (a lot of people just instead write to a variable they have no intention of using). This will create a Virtual network card on the host HyperV system, which can be seen in network connections. The name you set in HyperV for the name of the network will be the PNP device name, as shown below.. We then use that name to associate the PNP device to the network adapter, and then invoke good old netsh to set the adapter for us automatically. ## Why use those methods I realize that the PNP device name is actually a property directly available on the Win32_NetworkAdapter class, so why didn’t I use it? The short answer is that the NetworkAdapter can have some very odd behaviours sometimes (watch what happens to your MAC address when you disable the network adapter..) and to avoid those issue’s I only used properties of the class I knew I could rely on – namely the NetConnectionId. I could have also used WMI to set the IP address information, but it’s nowhere near as easy as calling netsh and certainly isn’t accomplished in a single neat line. There is no harm in doing it using WMI if you so wish (and that will be easier if you were doing complex configuration changes). Posted in Computing | Tagged: , | Leave a Comment » ## Integrating Operations Manager 2012 beta with Opalis / Orchestrator Posted by Matthew on October 10, 2011 I’m lucky enough in my lab environment to have access to both the Orchestrator beta and both SCOM 2007 and SCOM 2012 beta. I was recently tasked with creating a demo for a customer focused around SCOM 2012 and Orchestrator. Whilst an updated integration pack for SCOM 2012 has yet to be released for Orchestrator (or indeed, Opalis 6.3) you can use the existing IP just fine, providing you complete a few work arounds. ## Requirements First thing – you’re going to need access to the SCOM 2007 R2 media to be able to complete this. As directed by the SCOM Integration pack, install the SCOM 2007 R2 console on your action/runbook servers and your Client/Designer machines. If you attempt to use the SCOM 2012 console in it’s place you will (in my experience) receive connection errors when attempting to use the IP. ## Create Alert object workaround Secondly – In order to use the Create Alert object the Integration pack will normally deploy a management pack into SCOM automatically the first time it is used. Unfortunately the SDK for SCOM has changed and the method previously employed no longer works (you will receive an error stating as such when the object attempts to run). In order to resolve this, you will need to : 1. Have Opalis/Orchestrator raise an alert in a SCOM 2007 environment 2. Export the management pack from the SCOM 2007 environment that has been automatically imported. Note that as the MP is sealed, you will need to use the Export-ManagementPack powershell command as the GUI will have the export option grayed out. The management pack is called Opalis Integration Library.Get-ManagementPack | ? {$_.name -match ‘Opalis’} | Export-ManagementPack -path c:\Folder\
3. Import the management pack into your SCOM 2012 environment

Following this, you will now be able to use all of the IP objects in both SCOM 2007 and SCOM 2012.

For those without access to SCOM 2007, i’ve attached a copy of the management pack that you can import into your environment.  Note : The management pack is unsealed as it’s been exported from within a SCOM environment.  If you are uncomfortable importing an unsealed MP into your environment, do not do so, and instead utilize the method above to obtain your own (still unsealed) version of the MP.