Thursday, July 24, 2008

Automating Citrix Presentation Server installation

We just recently began upgrading our presenation server envrionment to CPS 4.5, and having quite a few servers to install we need a way to automate it. Currently we use some imaging software to clone the hard disk of a "gold" image, while this works for CPS 3.0 I have been warned about using the same process with 4.5. That and I really dont like the idea of imaging, its a hack that isnt necessary.

So I began looking for how to autoamte the installation - once the farm is setup it shoudl be a simple matter of passing some parameters on a command line to add a new server. Some quick googling turns up a blog by stealthpuppy that details everything I need (
I am in process of testing this now, and I expect that I can merge this script with other MSIExec options ( to automate the install of Presentation Server and all necessary patches

Tuesday, July 22, 2008

Variant types in SCOM

One of the items I have tried to have SCOM do is monitor network traffic on some of our routers/switches. The basics of this is fairly simple – create an SNMP monitor to poll on a set frequency and then store it as performance data. However I ran into issues with SCOM reporting that the variable type was wrong. The web site has a nice breakdown of what the variant types are when referenced by the MP.

  • Empty = 0
  • Null = 1
  • Short = 2
  • Integer = 3
  • Single = 4
  • Double = 5
  • Currency = 6
  • Date = 7
  • String = 8
  • Object = 9
  • Error = 10
  • Boolean = 11
  • Variant = 12
  • DataObject = 13
  • Decimal = 14
  • Byte = 15
  • Char = 16
  • Long = 17

Wednesday, July 16, 2008

My Printing Nightmare

Often times printing is a simple thing, especially in Windows. The print server hosts all the drivers and the client needs only to point to the server to download the necessary drivers and map to the printer. However some situations aren't quite so simple.

Take for instance printing in a Citrix or other Terminal Server environment. The multi-user environment means that a particular print driver can be loaded dozens of times concurrently, and if it isn't designed to do this then you can be in big trouble. Our environment is a little unique to other TS environments – we host the Terminal Server and Print Server at our location and we have no knowledge of the clients network. The printers are mapped via a logon script from the TS to the PS using model specific drivers and because of our technology model we cant use the Citrix Universal Print Driver. This sets the stage for the issues we are about to see.

Some of the issues we are seeing:

  • Printers aren't mapping correctly
  • Some printers fail to work intermittently
  • Printing works on some servers but not others, and the printers having issues change depending on who is logged in where
  • Adobe Acrobat freezes when opening docs
  • The issue comes and goes intermittently

So to begin troubleshooting I do my favorite item – I google the issue. Turns out this is a common thing in Citrix and TS environments where some print drivers cause havoc with the spooler, which is tied into just about everything on the computer. So I find a doc by HP that details all their printers that are supported in a Citrix environment ( and I remove all that aren't supported. I look at other vendor sites to see about their drivers and find some that are supported in Citrix, some that aren't, and a lot that just don't say. First step down and the environment looks better.

I also notice that our logon script is using a file "prnadmin.dll" to map printers. I have never seen anyone use this before – google does turn up some results – but I wonder if that may be part of the problem. I rewrite the script to use VBScript's oNetwork.MapWindowsPrinterConnection function instead and add in lots of error checking and reporting to ensure things are working properly.

So far so good, the issue appears to be stabilizing – until we added another printer. This specific HP printer doesn't have a PS driver included, instead they state that we should use the HP Universal Print Driver for it. So we install the driver on the Print Server and almost immediately begin having issues, different issues but more common issues.

So I call Microsoft for help and the first tier that I talk to waste most of my day and result in not making any progress on the solution. After I get off the phone with them I realize I can delete the print drivers from all the TS and restart the spooler to make the issue go away so I do that on all the servers to get the users up and running again. Its not a solution, but at least it works.

MS calls back and gives me a process to clear out all the 3rd party print processors and monitors from the servers. I begin hacking the registry as instructed with little success – the issues keep coming up several times a day.

Several more days I spend battling the nightmare when we finally decide to call a Citrix expert. He comes in and almost immediately identifies the HP Universal Print Driver as having issues – that's odd since HP specifically states that it can (and should) be used in a Citrix environment; we were even hoping that this universal driver would be our salvation for this issue. We call a couple other Citrix gurus and they both say the same – the HP UPD has "weird" issues in a Citrix environment. So we uninstall the driver and bump the effected printers to use the HP 4000 drivers that come with Windows.

The Citrix guys do give a glimmer of hope however, the additional steps take of limiting the drivers, processors, and monitors may have already resolved the initial issue, and that the most recent symptoms were caused by the HP UPD. Hmmm… I am skeptical but hopeful, I flush all the drivers from all the Terminal Servers to ensure they are reloaded from the print server and cross my fingers.

A few days later and some issues are occurring. It's the weekend and one of the IT admins are checking out the TSs to ensure they are ready for Monday and she is having lots of problems trying to print. Long story short – the admin had nearly 400 printers mapped in her profile and it was taking several minutes for the spooler to recognize them all. When we logged her out and logged in as a normal user with 3-4 printers mapped things worked fine. I had her remove the other printers from her profile and it sounds like things are working.

Its been a couple more days and only 1 issue has been reported – much better than the 4-5 issues per day. Below are the items done to get things working again.

  • Use only print drivers certified to work in a Citrix environment
  • Don't use any Version 2 print drivers, only Version 3
  • Don't use the HP UPD
  • Only use Microsoft default Print Processors and Print Monitors
  • Limit the number of printer drivers in use in the environment
  • Use delprof.exe (downloadable from MS) to delete old cached profiles

There is probably more, and I doubt this is the final step to resolution, but at least its better.

Monday, July 14, 2008

Monitoring services that are not set to Automatic start

The default service monitor employed in SCOM intelligently identifies if the service is set to Automatic startup and only monitors the service if it is. This is a helpful default so that if you set the service to Manual startup or Disabled for some administrative reason, then you don't get alerted on the service stopping. But what if there are services that you want to ensure are running regardless of the startup type? Maybe you want to ensure the AntiVirus is running everywhere and you want to be alerted if someone tries to disable it. Maybe you have a key service like SQL or Exchange that you manually start after any reboots and you need still need to know when it goes down or fails to be started. This will describe how to monitor a service state regardless of the startup state.

Step 1: Create the service monitor

In the SCOM Authoring Console, select the Health Model tab and the Monitors node

Select New | Windows Services | Basic Service Monitor

Enter in the applicable information in the General and Service Name tabs and click finish

Step 2: Edit the monitor to ignore startup type

Locate the monitor just created and open its properties

On the Configuration tab you will see 3 attributes

  • ComputerName
  • ServiceName
  • CheckStartupType

The last attribute is the important one and we need to set it to false, however simply typing false and clicking OK will not work for us.

On the Configuration tab click the Edit… button at the bottom of the window. There you will see something similar to this:

<Configuration p1:noNamespaceSchemaLocation="C:\ Temp\1\Client Telnet Monitor.xsd" xmlns:p1="">



<CheckStartupType />


The line "<CheckStartupType />" needs to be changed to "<CheckStartupType>false</CheckStartupType>" for the value to take effect.

Save the XML file, save the Monitor properties, and save the MP. The service monitor should now ignore the startup type of the service you specified to monitor

Monitoring Servers based on Server Name in SCOM

Most organizations have a standard naming scheme that they use based on server type, location, or department. For instance, the letters "DC" suggests a domain controller, "Mail" or "EX" suggests exchange, "SQL" suggests SQL servers, and "DR" could suggest disaster recovery (for location, not role). Based on these name standards we may want to manage the servers differently: do we really care about excessive network utilization on backup devices, or minor alerts on development systems?

Creating a group based on name is easy – simply create a group with dynamic criteria based on the name – but then applying overrides and monitors to it contains many issues. If you apply a monitor to the group, then when one of the systems in the group errors, the group will report the error without any detail on which machine caused it. To resolve this, I decided to create classes of servers based on their names.

Step 1: Create a Local Application class

In the SCOM Authoring Console, select the Service Model tab and the Classes node

Select New | Windows Local Application

Enter appropriate ID and Name, there are no Key Properties so that can be left blank

Step 2: Create a Discovery for the class

Select the Health Model tab and choose the Discoveries node

Select New | Registry (Filtered)

Enter in the ID and Name, for Target select Windows Computer or some similarly generic group

Leave Schedule and Computer as they are for now

On the Registry Probe Configuration step, click Add and select the following:

  • Object Type: Value
  • Key: ComputerName
  • Path: SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName\ComputerName
  • Attribute Type: String

On the Build Event Expression step, click Insert and select the following:

  • Parameter Name: Values/ComputerName
  • Operator: Matches regular expression
  • Value: (?i)dc.*

On the Discovery Mapper step, select the Class ID created in step 1, and select the Principal Name attribute.

Step 3: Export to SCOM and test

A few notes:

  • The path on the Registry Probe Configuration includes the path and attribute. My first round assumed that the Key property was appended to the Path property and it took me a while to identify my failure
  • The Value in the expression uses (?i) which is a regex expression stating to ignore case. This may or may not be needed in all environments
  • The dc.* in the event expression means that all computers whose names start with the letters "DC" will be included. This should change based on your naming schemes
  • Class types other than Local Application may work for this as well, this is just the most familiar to me for now
  • A WMI discovery can be done instead of a registry discovery if your systems are all W2k3 or greater. The reason for this is because prior OS's cannot handle the LIKE clause in the WMI query you need to run.
  • The Schedule defaults to 1/hour. This is helpful for the initial deployment, but you may want to decrease it to several hours or a day to limit overall performance

Adding custom data to SCOM alerts

Gratuitously stolen from

Adding custom information to alert description (s) and notifications

This is just a dump of some alert description variables I pulled from several other bloggers:

Custom Properties for Alert

Description and Notification:

Alert Description Variables:

For event Rules:

EventDisplayNumber (Event ID): $Data/EventDisplayNumber$
EventDescription (Description): $Data/EventDescription$
Publisher Name (Event Source): $Data/PublisherName$

EventCategory: $Data/EventCategory$
LoggingComputer: $Data/LoggingComputer$

EventLevel: $Data/EventLevel$

Channel: $Data/Channel$
UserName: $Data/UserName$

EventNumber: $Data/EventNumber$

For event Monitors:

EventDisplayNumber (Event ID): $Data/Context/EventDisplayNumber$
EventDescription (Description): $Data/Context/EventDescription$
Publisher Name (Event Source): $Data/Context/PublisherName$

EventCategory: $Data/Context/EventCategory$
LoggingComputer: $Data/Context/LoggingComputer$

EventLevel: $Data/Context/EventLevel$

Channel: $Data/Context/Channel$
UserName: $Data/Context/UserName$

EventNumber: $Data/Context/EventNumber$

For Repeating Event Monitors:

EventDisplayNumber (Event ID): $Data/Context/Context/DataItem/EventDisplayNumber$
EventDescription (Description): $Data/Context/Context/DataItem/EventDescription$
Publisher Name (Event Source): $Data/Context/Context/DataItem/PublisherName$

EventCategory: $Data/Context/Context/DataItem/EventCategory$
LoggingComputer: $Data/Context/Context/DataItem/LoggingComputer$

EventLevel: $Data/Context/Context/DataItem/EventLevel$

Channel: $Data/Context/Context/DataItem/Channel$
UserName: $Data/Context/Context/DataItem/UserName$

EventNumber: $Data/Context/Context/DataItem/EventNumber$

Performance Threshold Monitors:

Object (Perf Object Name): $Data/Context/ObjectName$
Counter (Perf Counter Name): $Data/Context/CounterName$
Instance (Perf Instance Name): $Data/Context/InstanceName$
Value (Perf Counter Value): $Data/Context/Value$

Service Monitors:

Service Name $Data/Context/Property[@Name='Name']$
Service Dependencies $Data/Context/Property[@Name='Dependencies']$
Service Binary Path $Data/Context/Property[@Name='BinaryPathName']$
Service Display Name $Data/Context/Property[@Name='DisplayName']$
Service Description $Data/Context/Property[@Name='Description']$

Logfile Monitors:

Logfile Directory : $Data/Context/LogFileDirectory$
Logfile name: $Data/Context/LogFileName$
String: $Data/Context/Params/Param[1]$

Logfile rules:

Logfile Directory : $Data/EventData/DataItem/LogFileDirectory$
Logfile name: $Data/EventData/DataItem/LogFileName$
String: $Data/EventData/DataItem/Params/Param[1]$


$Data/Context/DataItem/AlertId$ The AlertID GUID

$Data/Context/DataItem/AlertName$ The Alert Name

$Data/Context/DataItem/Category$ The Alert category




$Data/Context/DataItem/CreatedByMonitor$ True/False

$Data/Context/DataItem/Custom1$ CustomField1

$Data/Context/DataItem/Custom2$ CustomField2

$Data/Context/DataItem/Custom3$ CustomField3

$Data/Context/DataItem/Custom4$ CustomField4

$Data/Context/DataItem/Custom5$ CustomField5

$Data/Context/DataItem/Custom6$ CustomField6

$Data/Context/DataItem/Custom7$ CustomField7

$Data/Context/DataItem/Custom8$ CustomField8

$Data/Context/DataItem/Custom9$ CustomField9

$Data/Context/DataItem/Custom10$ CustomField10

$Data/Context/DataItem/DataItemCreateTime$ UTC Date/Time of Dataitem created

$Data/Context/DataItem/DataItemCreateTimeLocal$ LocalTime Date/Time of Dataitem created

$Data/Context/DataItem/LastModified$ UTC Date/Time DataItem was modified

$Data/Context/DataItem/LastModifiedLocal$ Local Date/Time DataItem was modified

$Data/Context/DataItem/ManagedEntity$ ManagedEntity GUID

$Data/Context/DataItem/ManagedEntityDisplayName$ ManagedEntity Display name

$Data/Context/DataItem/ManagedEntityFullName$ ManagedEntity Full name

$Data/Context/DataItem/ManagedEntityPath$ Managed Entity Path

$Data/Context/DataItem/Priority$ The Alert Priority Number (High=1,Medium=2,Low=3)

$Data/Context/DataItem/Owner$ The Alert Owner

$Data/Context/DataItem/RepeatCount$ The Alert Repeat Count

$Data/Context/DataItem/ResolutionState$ Resolution state ID (0=New, 255= Closed)

$Data/Context/DataItem/ResolutionStateLastModified$ UTC Date/Time ResolutionState was last modified

$Data/Context/DataItem/ResolutionStateLastModifiedLocal$ Local Date/Time ResolutionState was last modified

$Data/Context/DataItem/ResolutionStateName$ The Resolution State Name (New, Closed)

$Data/Context/DataItem/ResolvedBy$ Person resolving the alert

$Data/Context/DataItem/Severity$ The Alert Severity ID

$Data/Context/DataItem/TicketId$ The TicketID

$Data/Context/DataItem/TimeAdded$ UTC Time Added

$Data/Context/DataItem/TimeAddedLocal$ Local Time Added

$Data/Context/DataItem/TimeRaised$ UTC Time Raised

$Data/Context/DataItem/TimeRaisedLocal$ Local Time Raised

$Data/Context/DataItem/TimeResolved$ UTC Date/Time the Alert was resolved

$Data/Context/DataItem/WorkflowId$ The Workflow ID (GUID)


The Web Console URL

Target/Property[Type="Notification!Microsoft.SystemCenter.AlertNotificationSubscriptionServer"/PrincipalName$ The principalname of the management server

$Data/Recipients/To/Address/Address$ The name of the recipient (e.g. the Email alias to which the notification is addressed)