Wednesday, March 2, 2011

Update Outlook 2003 clients with CAS Array Name?

One of the most enduring and painful shortcomings of the new RCA (RPCClientAccess) service in Exchange 2010, is it's inability to refer downlevel clients to the appropriate CAS server.  If you are using Outlook 2007 or 2010, this process is handled by the autodiscover service, but what to do if you have Outlook 2003 clients?  Unfortunately there are no really good options, but I will list some of what I have seen work at various customers.  To the best of my knowledge, the only supported method is to deploy a PRF file (also included below) or to manually change each client.  Ideally you would have created a CAS Array from the start and never had this problem.  But suppose you needed Kerberos authentication pre SP1, or you just plain made a mistake?

1) Swing server.  This seems like overkill, but it may be less work and easier than visiting every desktop in some scenarios.  The referal mechanisms still fucntion between Exchange 2003/2007 and Exchange 2010.  You could move mailboxes to a temporary Exchange 2007 server and then move them back to Exchange 2010.  Keep in mind that users will have to connect at least once to the mailbox while it is homed on the Exchange 2007 server for this procedure to be effective.  Also the move mailbox from 2010 to 2007 will incur downtime, but 2007 to 2010 the mailbox moveback will keep the mailbox online.

2) PRF File.  http://office.microsoft.com/en-us/office-2003-resource-kit/customizing-outlook-profiles-by-using-prf-files-HA001140258.aspx

3) VBScript.  In some cases, the PRF file simply doesn't work, or there is no easy way to deploy it.  I have included some sample VBScript at the end of this post that should help some advanced users.

4) Exchange 2003/2007 Spoof.  Don't try this one at home kids!  if you feel like rolling the dice or are very desperate, you could try the following.  Add host file entries on all Exchange servers and relevant domain controlllers for the CAS that is currently in the Outlook 2003 user profile 'server name' field.  Remove the SPN for that CAS (this will disable Kerberos authentication temporarily).  Change the A record for the CAS in DNS such that it points to the IP of an Exchange 2003 or 2007 server.  When clients log on, they will connect to the old Exchange 2003 or 2007 server and get referred to the CAS Arry name.  Once you are confident that most clients have had their Outlook profiles updated, undo the changes and add the SPN back in.

Sample VBScript

Const ServerName = <CAS Array FQDN>
Const ServerHex = <CAS Array FQDN in Hex>
Dim defaultProfile

defaultProfile = GetDefaultProfile("HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\DefaultProfile")
WriteRegistryFileAndMerge defaultProfile, ServerName, ServerHex

Function GetDefaultProfile(RegistryKey)
Dim WshShell
Dim strReturn

    Set WshShell = CreateObject("Wscript.Shell")
    If Len(RegistryKey) Then
        strReturn = WshShell.RegRead(RegistryKey) 'Check parm value
        If Err.Number = 0 Then
            GetDefaultProfile = strReturn
            On Error GoTo 0
            Exit Function
        Else
            Err.Clear
        End If
    End If

    Set WshShell = Nothing
    GetDefaultProfile = strReturn
    On Error GoTo 0
End Function

Function WriteRegistryFileAndMerge(ProfileName, name, binary)
 Set objFSO = CreateObject("Scripting.FileSystemObject")
 Set file = objFSO.CreateTextFile("profile_merge.reg", True)

 file.WriteLine("Windows Registry Editor Version 5.00")
 file.WriteBlankLines(1)
 file.WriteLine("[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\" & ProfileName & "\04ed552946e5ea48a65bcb2f19db0409]")
 file.WriteLine("""001e660c""=" & name & """")
 file.WriteLine("""001f662b""=hex:" & binary)
 file.WriteLine("""001e6614""=""/o=<organization>/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=" & name & """")
 file.WriteBlankLines(1)
 file.WriteLine("[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\" & ProfileName & "\13dbb0c8aa05101a9bb000aa002fc45a]")
 file.WriteLine("""001f662a""=hex:" & binary)
 file.WriteLine("""001e6602""=""" & name & """")
 file.WriteLine("""001e6612""=""/o=<organization>/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=" & name & """")
 file.WriteLine("""101e6613""=hex:" & binary)
 file.WriteBlankLines(1)
 file.WriteLine("[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\" & ProfileName & "\aa1c0662f29b1c42aa3d30610610f421]")
 file.WriteLine("""001e660c""=""" & name & """")
 file.WriteLine("""001f662b""=hex:" & binary)
 file.WriteLine("""001e6614""=""/o=<organization>/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=" & name & """")
 file.WriteBlankLines(1)
 file.WriteLine("[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\" & ProfileName & "\efa40b5e07b9204abdc646aa5e83a6be]")
 file.WriteLine("""001e660c""=""" & name & """")
 file.WriteLine("""001f662b""=hex:" & binary)
 file.WriteLine("""001e6614""=""/o=<organization>/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=" & name & """")
 file.WriteBlankLines(1)
 file.WriteLine("[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\" & ProfileName & "\ff83a0e41446294d95bda883831cb0a9]")
 file.WriteLine("""001e660c""=""" & name & """")
 file.WriteLine("""001f662b""=hex:" & binary)
 file.WriteLine("""001e6614""=""/o=<organization>/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=" & name & """")
 file.Close()
 Set file = Nothing

 Set WshShell = CreateObject("Wscript.Shell")
 WshShell.Run "regedit /s profile_merge.reg", 1, True
 Set WshShell = nothing

End Function

Grade:  Why Did I Do That?

4 comments:

  1. Elegant and well presented! The VBS solution is perfect for a circumstance with the additional complication of hundreds of mandatory profiles swarming a Terminal Server.

    ReplyDelete
  2. This is excellent stuff here. The only thing is number 4 is the thing of consultants dreams for people calling to say that they're trying to do this and "for some reason it doesn't work". While you can do it, it's pretty uncommon for most people to know about setspn and kerberos tickets.

    ReplyDelete
  3. I have a question about #3 and #4. For option 3, it seems as if those registry values are all randomly generated IDs. So every user has a different set of ID registry keys within their Default Profile key. So how can you hardcode those registry keys in there when they'll be different for every user?

    As for option #4, what SPN are you supposed to delete? There are a lot of SPNs for an Exchange 2010 server. For example:

    MSServerClusterMgmtAPI/serverName
    MSServerClusterMgmtAPI/serverName
    exchangeRFR/serverName
    exchangeRFR/serverName
    exchangeAB/serverName
    exchangeAB/serverName
    exchangeMDB/serverName
    exchangeMDB/serverName
    SMTP/serverName
    SMTP/serverName
    SmtpSvc/serverName
    SmtpSvc/serverName
    WSMAN/serverName
    WSMAN/serverName
    TERMSRV/serverName
    TERMSRV/serverName
    RestrictedKrbHost/serverName
    HOST/serverName
    RestrictedKrbHost/serverName
    HOST/serverName

    Do you delete all of them and then add all of them back in after?

    Thanks for the help!

    ReplyDelete
  4. Just wanted to post an update to this. I attempted #4 and it worked without a hitch! Thanks for the suggestion. It was really the only one in the list that worked seamlessly.

    ReplyDelete