Bulk configuring & enabling OCS users


Not Exchange related, but something I’d like to share with you is a script to bulk configure and enable users for OCS with enterprise voice. In the process, the telephone numbers are also changed, since often the customer is moving to a new range of numbers as well.

The information was provided by the customer in an Excel sheet, which I exported to a CSV file. Since the script was to be run on an Windows Server 2003 box, I opted for a simple VB script, which you can find below.

A short explanation:

  • When the telephone number has a value, the user is configured for enterprise voice (intOptionFlags 896). If the telephone number is empty, the user is configured for IM and presence (intOptionFlags 256);
  • You can expand the sheet (CSV) with extra columns. When you need to create colums before the current ones, don’t forget to modify the index of the arrFields() references accordingly;
  • Change the OCSHomeServer to the proper pool value;
  • Change the OCSLocationProfile to the proper value;
  • Change the OCSPhoneContext to the proper value;
  • If you want to see what it will do first, set TestMode to True;
  • Use it in a lab environment first; test, test, test!

Note: If you have problems finding out the value of the OCSHomeServer, OCSLocationProfile or OCSPhoneContext settings, configure one user with the proper settings using ADUC, and inspect the values of those settings by using ADSIEdit or LDP.

users.csv

name;samaccountname;telephonenumber
Francis Blake;francis.blake;+31 (0) 30 123 45 11
Philip Mortimer;philip.mortimer;+31 (0) 30 123 45 22

OCSEnableUsers.vbs

'*--------------------------------------------------------------------------------
'* Name         : OCSEnableUsers
'* Created By   : Michel de Rooij
'* E-mail       : michel@eightwone.com
'* Date         : 20101118
'* Version      : 0.1
'*--------------------------------------------------------------------------------
'* Changes:
'* 0.1 Initial version
'*--------------------------------------------------------------------------------

On Error Resume Next

dim oConn, strQry, rs, objUser, strVal, objFSO, objFile, strLine, arrFields, i, line
dim strSAM, strTel
dim strServerURI, strLineURI, strSIP, strExtension, intOptionFlags

Const ADS_PROPERTY_APPEND = 3

Const OCSHomeServer     = "CN=LC Services,CN=Microsoft,CN=OCSPOOL1,CN=Pools,CN=RTC Service,CN=Services,CN=Configuration,DC=contoso,DC=com"
Const OCSLocationProfile= "CN={820ADF85-B64C-4F32-92F0-E4AA37267677},CN=Location Profiles,CN=RTC Service,CN=Services,CN=Configuration,DC=contoso,DC=com"
Const OCSPhoneContext   = "L0CDP.L1UDP@OCS2.contoso.com"

Const TestMode        = False

set oConn= createObject("Adodb.Connection")
oConn.provider = "AdsDSOObject"
oConn.open "ADs Provider"

set objFSO= createObject("Scripting.FileSystemObject")
set objFile= objFSO.OpenTextFile("users.csv", 1, True)

wscript.echo "RUNNING IN TESTMODE IS "& TestMode

line= 1
while not objFile.AtEndOfStream
 strLine= trim(objFile.readline)
 if Line> 1 Then
 arrFields= split(strLine, ";")
 strSAM= arrFields(1)
 strTel= normalizePhone( arrFields(2))
 strTelNew= replace( replace( arrFields(3), "(0)", ""), "  ", " ")

 wscript.echo strSAM&" "& strTel
 strQry= "<LDAP://dc=contoso,dc=com>;(samAccountName="& strSAM& ");adspath;subtree"
 set rs= oConn.execute( strQry)
 if rs.recordCount > 0 Then
 while not rs.EOF
 set objUser= getObject( rs.fields(0).value)
 wscript.echo "User found: "& objUser.distinguishedName
 wscript.echo "Previous Phone No: "& objUser.TelephoneNumber

 strSIP= "sip:"& objUser.mail
 strExtension= right( strTel, 3)
 strLineURI= "tel:"& strTel& ";ext="& strExtension
 strServerURI= "sip:"& strExtension& ";phone-context="& OCSPhoneContext

 If strTel= "" Then
 intOptionFlags= 256
 Else
 setAttr objUser, "msRTCSIP-Line", strLineURI
 setAttr objUser, "msRTCSIP-LineServer", strServerURI
 intOptionFlags= 896
 End If

' Set AD fields
 setAttr objUser, "telephoneNumber", strTelNew

 ' Set OCS props
 setAttr objUser, "msRTCSIP-UserEnabled", True
 setAttr objUser, "msRTCSIP-PrimaryHomeServer", OCSHomeServer
 setAttr objUser, "msRTCSIP-PrimaryUserAddress", strSIP
 setAttr objUser, "msRTCSIP-UserLocationProfile", OCSLocationProfile
 setAttr objUser, "msRTCSIP-OptionFlags", intOptionFlags

 addAttr objUser, "proxyAddresses", strSIP

 If Not TestMode Then
 objUser.SetInfo
 End If

 rs.moveNext

 wend
 Else
 wscript.echo "*** WARN: User not found in AD: "& strSAM
 End If

 Else
 ' Skip header
 End If
 line= line+ 1
wend 

objFile.close
set objFSO= Nothing

Function setAttr( objUser, strAttr, strVal)
 wscript.echo "Setting "& strAttr& " to "& strVal
 If TestMode Then
 ' ...
 Else
 objUser.put strAttr, strVal
 End If
End Function

Function addAttr( objUser, strAttr, strVal)
 wscript.echo "Adding "& strVal& " to "& strAttr
 If TestMode Then
 ' ...
 Else
 objUser.PutEx ADS_PROPERTY_APPEND, strAttr, array(strVal)
 End If
End Function

Function NormalizePhone( Tel)
 NormalizePhone= replace( replace( tel, " ", ""), "(0)", "")
End Function

LUN design and Hardware VSS


I had a question why you need to design seperate LUNs for Exchange database and log files when using a hardware based Volume Shadow Copy Service (VSS) backup solution, as mentioned in this TechNet article:

To deploy a LUN architecture that only uses a single LUN per database, you must have a database availability group (DAG) that has two or more copies, and not be using a hardware-based Volume Shadow Copy Service (VSS) solution.

The reason for this requirement is that hardware VSS solutions operate at the hardware level, i.e. the complete LUN. Therefor, if you put the Exchange database and log files on a single LUN, it will always create a snapshot of the whole LUN. This restricts your recovery options, since you can by definition only restore that complete LUN, overwriting log files created after taking the snapshot. So, changes (log files) made after the snapshot are lost and you have no point-in-time recovery options.

For example, with the database and log files on a single LUN, suppose you create a full backup on Saturday 6:00. Then, disaster strikes on Monday. By definition, you can now only restore the database and log files as they were on Saturday 6:00; log files which were created after Saturday 6:00 are lost.

With the database and log files on separate LUNs, you can restore the database LUN, which leaves the LUN with the log files intact. Then, after restoring the database, you can start replaying log files.

So, keep this in mind when planning your Exchange LUNs in conjunction with the backup solution to be used. Note that the Mailbox Role Calculator supports this decision by letting you specify Hardware or Software VSS Backup/Restore as the Backup Methodology to be used.

If you’re interested in more background information on how VSS works, I suggest you check out this TechNet article.

Note: This blog has also been published on Exchange fellow Jaap Wesselius’ ExchangeLabs blog here.

Exchange & Windows Phone 7


This TechNet article on Windows Phone 7 got my attention. It appears you cannot fully utilize Exchange ActiveSync mailbox policies, unless you set AllowNonProvisionableDevices to True. If you don’t do that, you can only use the following properties, otherwise synchronization issues might be experienced:

  • PasswordRequired
  • MinPasswordLength
  • IdleTimeoutFrequencyValue
  • DeviceWipeThreshold
  • AllowSimplePassword
  • PasswordExpiration
  • PasswordHistory
  • DisableRemovableStorage
  • DisableIrDA
  • DisableDesktopSync
  • BlockRemoteDesktop
  • BlockInternetSharing

Another option is to create a seperate policy for Windows Phone 7 users.

Another thing worth mentioning is that when using multiple Exchange accounts on your Windows Phone 7, policies will be merged into a most restrictive set (credit to Dave Stork who got the information at TEE10).

JetStress updated


A quick note to inform you the the JetStress tool has been updated to version 14.1.225.17.

The online documentation on TechNet is currently being revised (article 706601). Currently on the following sentence has been removed from the article:

“You should test Jetstress 2010 with Exchange 2010 ESE binaries, and use Jetstress 2007 for testing legacy ESE versions of Exchange 2007 and Exchange 2003”

The JetStress tool can be used to simulate disk I/O load on a test server running Exchange to test and validate performance and stability of the disk subsystem, prior to moving them into a production environment.

The toolkit page has been updated accordingly.

You can download it here; x86 version is located here.

Exchange 2010 Visio Stencil


A quick post, but helpful for all those involved with designing and drawing out infrastructure diagrams related to Microsoft Exchange Server. Microsoft published Visio stencil with shapes for Microsoft Exchange Server 2010 (RTM and SP1). These shapes include icons for the following:

  • Exchange 2010 server roles
  • Features new to Exchange 2010 SP1
  • Networking, telephony, and Unified Messaging objects
  • Active Directory and directory service objects
  • Client computers and devices
  • Other Exchange organization elements
  • Cloud elements

You can download the stencil, which is suited for Visio 2007 as well as Visio 2010, here; it has also been added to the toolkit page.