My current customer uses a strong naming convention for their Exchange Servers.  This enables them to quickly and easily determine what role and which domain a server is located in.

Their algorithm for naming goes a little like this: EXCH-<DomainID>[RoleID]-<Node#>, where:

DomainID = a two-character identifier for the domain
RoleID = a two- or three-character identifier for the server role
Node# = a two-digit server number

So, an example of this might be EXCH-RDCAS-01, for Exchange server, Redmond domain, Client Access server, #1.  Might also have EXCH-RDHT-01, or EXCH-RDUM-01.

A variant on this is mailbox clusters and cluster nodes.  Since there is more detail, the convention changes slightly: EXCH-<DomainID>-<Cluster#><C or S><Node#>, where:

DomainID = same as above
Cluster# = mailbox cluster #
C or S = CCR node or SCR target
Node# = usually a 1 or a 2

One of my primary deliverables for the current phase of their Exchange Server 2007 project is automated installation scripts.  To simplify things, I’ve been writing a single consolidated “InstallExchange.ps1” script that will automatically determine the role of the server and install/configure as appropriate.

To determine the server role, I previously used overly complex logic to parse out the name based on hyphens (-), then did a lot of System.String.Substring() calls to grab two characters from there, three from over here, is there a C in it, etc. 

I was looking at some other .NET stuff, and realized that I can use a regular expression to both validate that the name matches the convention but also have PowerShell (which is built on .NET) doing the parsing for me.

The regular expression that does the job is:

^(EXCH)-(\w{2})(\w{2,3})?-(\d+)(([C,S])(\d{1}))?$

In PowerShell, you use the –match operator to apply a regular expression against a particular string or variable.

In code, this looks like:

$ValidNameRegEx = “^(EXCH)-(\w{2})(\w{2,3})?-(\d+)(([C,S])(\d{1}))?$”

if( $MachineName –match $ValidNameRegEx )
{
      # … do stuff …
}

A great benefit from using regular expressions in PowerShell is the $matches hashtable that is automatically generated that contains the results of any groupings you specify.

In the example above, the parenthesis surround specific items that I want to call out explicitly.  The –match operation returns a $matches object that has the following array items, in order of matching:

$matches[0] : The entire string that matched
$matches[1] : The literal string “EXCH”
$matches[2] : The domain identifier (such as “RD” or “DZ”) – 2 characters max
$matches[3] : The role identifier (like “HT” or “CAS” ) – 2 or 3 characters.  Optional (if mailbox server)
$matches[4] : The server OR cluster number (Node ID/Cluster Number)
$matches[5] : Mailbox Cluster: the entire C1, C2, S1, S2 string.  Not used.
$matches[6] : Mailbox Cluster: The C or S designator for CCR or SCR.
$matches[7] : Mailbox Cluster: The cluster node number

This allows me to make my code much simpler to write and cleaner to read.  The … do stuff … section above then becomes:

$DomainID = $matches[2]

switch( $matches[3] )
{
      “HT” { $ServerRole = “HubTransport” }
      “CAS” { $ServerRole = “ClientAccess” }
      “UM” { $ServerRole = “UnifiedMessaging” }

      # … so on and so forth ….
}

Using regular expressions, I was able to remove a good chunk of string parsing code and streamline the process.  I also took a step and moved the parsing code into a separate code file that can be shared by many scripts that all need to do this operation (like disk configuration).  This is accomplished by dot sourcing… or simply calling:

. .\GetServerRole.ps1

inside of your script.  Take note of the lone period (.) in front of the script name.

If you are writing your own PowerShell scripts and need a drive-by course on regular expressions, Regular-Expressions.info has a lot of good information and a decent tutorial that can help you get started.