System Center, Automation, Powershell and other Thoughts

SEP 11: Pattern File Age Monitor

A customer asked me to monitor the age of the pattern files of the Symantec Endpoint Protection 11 Client (SEP11) on its server systems.

As I didn’t found an Symantec SEP Management Pack, I decided to create it on my own.

Perhaps someone could make use of it too, I decided to show it step by step.

Lets start

In the Authoring view select Monitor and “Create a Monitor” on the right site.

1. Select the Monitor type to create: “Timed Script Three State Monitor”
2. Change the Management Pack, for example, create a new one called “_SEP”

3. Name the Monitor and add a description
4. Select the target for the monitor: (in our case, all computers) Windows Computer
5. Make sure that “Monitor is enabled” is checked

6. Set a value how often the monitor will run and check for the pattern file age
(normally once a day should be enough, but that way it would take also one day to close the alerts automatically if the pattern are updated)

7. Add a script name (make sure that the name of the script is unique to avoid conflicts with other Management Packs)
8. Add the script that collects the pattern age from the registry of the computer system

Dim oAPI, oBag
Set oAPI = CreateObject("MOM.ScriptAPI")
Set oBag = oAPI.CreatePropertyBag()
const HKEY_LOCAL_MACHINE = &H80000002

badState = 10
warningState = 5

Set objRegistry = GetObject("winmgmts:root\default:StdRegProv")
strKeyPath = "SOFTWARE\Wow6432Node\Symantec\Symantec Endpoint Protection\AV"
strValueName = "PatternFileDate"

objRegistry.GetBinaryValue HKEY_LOCAL_MACHINE,strKeyPath, strValueName, strValue
If IsNull(strValue) Then
 strKeyPath = "SOFTWARE\Symantec\Symantec Endpoint Protection\AV"
 strValueName = "PatternFileDate"

 objRegistry.GetBinaryValue HKEY_LOCAL_MACHINE,strKeyPath, strValueName, strValue 

End If

If Not IsNull(strValue) Then

y = 1970 + strValue(0)
m = 1 + strValue(1)
d = strValue(2)

date1 = CDate(y & "/" & m & "/" & d)
date2 = now
diffdays = DateDiff("d",date1, date2)


diffdays = -1

End If

if diffdays >= badState then

 Call oBag.AddValue("state","BAD")
 state = "BAD"

if diffdays >= warningState then

  Call oBag.AddValue("state","WARNING")
 state = "WARNING"
 Call oBag.AddValue("state","GOOD")
 state = "GOOD"
end If

end if

Call oAPI.LogScriptEvent("SEPPAtternFileState.vbs", 101, 2, "Patternstatescript delivered state " & state & ". Pattern File age is " & diffdays & " days.")
Call oBag.AddValue("PatternDateTimeToNowDiff",diffdays)

Call oAPI.Return(oBag)

9. Add the BAD state. (If the script returns a BAD)

10. Add the WARNING state. (If the script returns WARNING)

11. Add the GOOD state. (If the script returns GOOD)

12. Set the monitor state corresponding to the script result.

13. Enable the check box for alert generation
14. Change the dropdown “Generate an alert when: The monitor is in a critical or warning health state”
15. Add an alert name (this is what you’ll see when the error is thrown)
16. Change the severity to: “Match monitor’s health”
17. Add an alert text. Mine can be found here (it includes the computer name an the age of the pattern files and a few common resoulution possibilities)

SEP Pattern files on $Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$ are $Data/Context/Property[@Name='PatternDateTimeToNowDiff']$ days old!


1. Please check if enough space on systemdrive left.

(app. 400MB)

2. Check if Live Update Server is reachable

3. Check if SEP Service is running

4. Reinstall SEP Client


Using these steps you can easily add the SEP pattern file age monitor to your SCOM.
Things you can do if you want to make it more professional:

  • build an management pack including discovery for computers where SEP is installed
  • add parameters for overrides, so warning and error threshold can be overridden without changing the script
    (actualy it will warn if pattern are 5 or more days old and error when pattern are 10 or more days old)
  • this script can also be used to build a rule for performance collection

But this way, it is done in round about 5 minutes.

Kind regards,

KMS MP: Idle Minutes Monitor Alert

A customer of mine had several “Idle Minutes Monitor Alert” raised by the Key Management Server MP.

The eventlog for KMS on the KMS Server stated, that there was an KMS request round about every 30 seconds.
So the error was definitiv a false positive.

The treshold for the monitor was default (480 minutes).

I inspected the monitor and saw in the configuration, that the last activity in KMS is stored in the operations manager.
These values are inserted through a scheduled discovery that runs every 15 minutes.

I exported the management pack and had a look on that discovery. There I found an VBS script that does a lot of WMI queries.

As the KMS Server is a Server 2008 R2, and there is a WMI Memory Leak on excessive usage of WMI, I installed the corresponding hotfix and the error was gone.
This hotfix is: KB981314 (

Kind regards,


Failed Accessing Windows Event Log: Microsoft-Windows-BranchCache/Operational

I stumbled about the following warning at a customer:

The warning was thrown for several servers and claimed, that the special eventlog for the feature “branch cache” was not able to be read.
Inspecting the systems didn’t show up that the branch cache feature installed.
Also netsh branchcache show status brought up the message: “This command can only be executed when BranchCache is installed.”

The problem was, that branch cache was installed on the systems brought up a warning, but not needed anymore.
While they where installed and configured, SCOM has discovered the systems.
So I installed the brach cache feature again, set the branch cache to disabled using netsh and uninstalled branch cache feature.

After that I disabled the discovery rules shown in the screenshot below.

Next step was to remove the disabled discoveries from the database using the powershell.


After that, I removed the disable overrides.

So the warnings didn’t appear again.

SCOM R2 Agent push failed with error 80070102 and 8000FFFF

We had several new server with Server 2008 R2 that where identically installed.
On non of this systems we where able to push out the scom agent.

A look at the push log file on the management server (gateways in our case) showed the error message 8000FFFF and something about: registering a firewall rule failed.

Strange, the firewall was disabled on all systems. So, we had a look at the rules on one of the servers and saw a rule called “MOM Agent Installer Service”.
Deleting this rule started to make the push work like a charme.

Digging into the closed monitors on the SCOM, we saw, that the first push failed with the message:
“A system update is in progress”.

So, because of the windows update reboot while the first push was tried, the agent wasn’t installed, but the firewall rule not deleted successfully.


If push fails with error 80070102 and 8000FFFF in the log, have a look at the firewall on the system, even it is disabled.

‘MOM.scriptAPI’ does not return property bag in Powershell ISE

When implementing a new management pack for SCOM 2007 R2, most of the time I try to use Powershell instead of VBScript.
For the development I normally use notepad++, but since this wasn’t installed at customers’ I tried using the ISE.

After an hour of troubleshooting, I switched to the console host of Powershell, and the script was working as suspected.
The code that confused myself are only a few lines:

$api = new-object -comObject 'MOM.ScriptAPI'
$bag = $api.CreatePropertyBag()



Running the code in the ISE returns: NOTHING

Running it in the normal console host, retruns the xml structure of the SCOM property bag as suspected.

So, using notepad++ and the consolehost for deployment of managment pack scripts is my recommended way at the moment…

Hashtable doesn’t contain a method ‘Ádd’

The powershell has a really nice implementation of a dictionary. It is called Hashtable and can be used to store pairs of keys and values.
Compared with the dictionary used in vbscript, it is really simple to use,
and I have used it several times befor. Till last friday:

There is a method called ‘Add’, really!
And running a get-member agains a hashtable shows at the first entry:

Name         MemberType      Definition
—-              ———-                 ———-
Add            Method                  System.Void Add(System.Object key, System.Object value)

So where the hell does this error come from.
I decided to make a set-psdebug -step in the powershell ISE.
Have a look what I’ve found:

Yes, you can trust your eyes, there is an acute accent on top of the A
Add -> Ádd

Ok, so where are my glasses:

As you can see, using the ISE with a Font Size of 12
and a sceen resolution of 1920 x 1200
makes it hard to see everything clear.

And I’m really glad, that this wasn’t a real bug to my favorite object hashtable.

Get the IPAddresses from all computers in your Active Directory

A colleague of mine asked, how to retrieve the IPs from all servers in an active directory quickly.
Here is the answer:

#build a directorysearcher with ldap filter to get only computers
#if only a single server should be determined, change the * in name=* to name=<servername> (without <>)
$ds = new-object system.directoryservices.directorysearcher("(&(objectcategory=computer)(name=*))")

#get the computernames only
$computers = @($ds.findall() | % { ([adsi]$_.path).properties['name'] })

#loop through the names and try collect the IPs using wmi and list them
foreach($c in $computers)
Get-WmiObject -computer $c -query "select * from win32_networkadapterconfiguration" | where-object { $_.ipaddress.count -gt 0 } | foreach-object { "$($c): $($_.ipaddress)" }

Have fun.

SCOM Console – Remove Entry from “Registered Servers”

A customer accidently removed his old SCOM 2007 RMS and installed a completely new 2007 R2 with a new name for the managmentgroup.
After removing the ad integration out of the active directory, the server was still showing up in the SCOM logon console under “Registered Servers”.

So we removed it that way:

1. Open up ADSI in the default naming context.
2. Navigate to the server that is shown but not wanted anymore.
3. Remove the “CN=SDKServiceSCP” under the server object.

Documentation made easy – Convert Problem Step Recorder File to HTML

Since Windows 7 and Server 2008 the build in tool “Problem Step Recorder” can make screenshots automatically on every click that is made. It is perfect for building installation howto’s or any other kind of documentation. Yes, there are more powerfull tools on the market, but hey, its for free… 
Only problem is, the files that are delivered as zipped MHT-Files only. So only browsers can show them. You are not able to import them for editing directly into Microsoft Word.

So I decided to build a little parser script in Powershell that converts the mht files from psr.exe into its html-files and jpeg’s.

This script takes the filepath of the zipfile or the unzipped mht file and extracts the hmtl, css, and jpeg’s into a subfolder:

param($file=$(read-host "filename of psr-zip or psr-mht file? "))

function writefile($dir, $fname, $text)
    $text | out-file -append $dir\$fname -Encoding "default"

function convertJPG($dir)

$jpgfiles = get-item $dir\*.jpeg.txt
foreach($jpg in $jpgfiles)
        $filename = $

        "$filename -> $($filename.substring(0,$filename.length-4))"

        [System.Convert]::FromBase64String((Get-Content $jpg -readcount 0)) | set-content -Encoding Byte "$dir\$($filename.substring(0,$filename.length-4))"
        remove-item $dir\$filename -force

function extractPSR($zipfile, $destfolder)
 $shellApplication = new-object -com shell.application
 $zip = $shellApplication.Namespace($zipfile)
 $dest = $shellApplication.Namespace($destfolder)
if(test-path $file)
$file = get-item $file

$folder = (get-date -Format "yyyyMMddHHmmss").tostring()
$folderObject = new-item $folder -type directory -force
$filename = ""

 $unzipdest = "$($folderobject.fullname.tostring())\temp"
 new-item $unzipdest -type directory -force | out-null
 extractPSR $file.fullname $unzipdest
 $psrfile = get-item "$unzipdest\*.mht"
 $psrfiles = $file

$content = get-content $psrfile

"Start: creating files in folder $pwd\$folder"

foreach($line in $content)
  switch -wildcard ($line)
    "Content-Location: *"
        $filename = $line.split(":")[1].trim()
            "writing: $filename.txt"
            "writing: $filename"

    "--=_NextPart_*" { break; }

    "Content-Type: *" { break; }

    "Content-Transfer-Encoding: base64" { break; }

        if($filename -ne "")
                if($line -ne "")
                    writefile $folder "$filename.txt" $line

                writefile $folder $filename $line


"Finished: Creating files"
"Start: converting pictures from text to JPG"

convertJPG $folder
"Finished: converting pictures"

$yesno = read-host "Open containing folder? [y] "

if($yesno -eq "" -or $yesno.tolower() -eq "y")
    &explorer.exe $pwd\$folder
    "ERROR: $pwd\$file not found"

Next thougts are to convert it into a standard documentation directly or crop the slideshow of.

But these are plans for the future,
as well as adding some more comments to the code ;-)


As there are several errors with the linefeeds while copying the source code, here you can download it as a .zip-File

Bitlocker Pin Tool on Codeplex


as written in the post “Change Bitlocker PIN without administrative rights using SCCM” we builed a little gui for non administrative users to change the bitlocker pin.

We where really astounded about the feedback and the questions on how to get the tool or the source code. So we decided to bring it up on Codeplex.

And here it is:

Project Description
Deploying Bitlocker with Windows 7 in enterprise environments works pretty nice with the new features which have beend implemented by microsoft. There’s still one big problem to solve. Users can’t change their PBA Bitlocker PIN without administrative priviledges.

Feel free to give away this link and grab the tool on codeplex.