Thursday, February 4, 2010

Modifying Outlook’s Exchange Proxy Settings Programmatically using C#

Modifying Outlook settings using C# is relatively straight forward.  There is, of course the Outlook Object Model that will allow you to manipulate the behavior of Outlook and the Extended MAPI APIs that will provides access to the messaging subsystem.  However, neither of these approaches allow for a simple modification of an existing Outlook Profile.  To accomplish this, it’s best, IMHO, to directly edit the registry.

My specific directive was to modify the “On Fast Networks, Connect using HTTP…” setting.  My client had non-domain joined laptop users that he wanted to force into HTTP mode, largely because these laptops were often moving between wired/wireless/vpn networks and firewalls were preventing RPC traffic in some cases.  While Outlook should fall back to HTTPS, it was not and as a result, Outlook on non-domain joined laptops would hang when clients moved from one network to another.

The long term fix for this problem is, of course, to get laptops into the domain.  Once in the domain, a user certificate can be issues from the AD-integrated PKI and the laptops can be directed to an 802.11 wireless network.  The new wireless network will not have any port restrictions and allow TCP connectivity to Exchange.

In the meantime, my client needed a piece of utility code that would modify the Outlook profile and force HTTP connections in all circumstances.

My research uncovered some pointers to where in the registry I could make these changes.  I learned that most registry values are Binary and have specific values that will create various combinations inside the Outlook Profile.

For the Exchange Proxy Settings section of the profile, the following registry keys are located under:

HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Outlook\13dbb0c8aa05101a9bb000aa002fc45a

00036623  (REG_BINARY) = Enables/Disables the “Connect using HTTP” box.
001f6622   (REG_BINARY) = Sets the address for the first text box labeled as https://
001f6625  (REG_BINARY) = Sets the address for the second text box labeled as “Principal name for proxy server”
00036627  (REG_BINARY) = Sets the the authentication type.  (01000000 = Basic, 02000000 = NTLM)
00036601 (REG_BINARY) = Sets cached Exchange mode.   (84010000 = Enabled.   84050000 = Enabled with public folders/favorites.  04000000 = Disabled.)
001e6608 (REG_SZ) = Stores the TCP/IP address, the NetBIOS computer name, or the DNS FQDN used to create the initial profile.
001e6602 (REG_SZ) = Stores the NetBIOS computer name where the mailbox is located.

So my code needs to open this registry path and modify the 00036623 Key.

I started by setting several variables, including the path to the hive and the key.  I also set the binary value for turning on “On fast networks, connect using HTTP first, the connect using TCP/IP”

image

static void Main(string[] args)
{
    Console.WriteLine("Turning on Outlook Anywhere support for fast networks....");
    String sKeyPath = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles";
    string oLPKey = "13dbb0c8aa05101a9bb000aa002fc45a";
    string oLOFNKey = "00036623";
    Byte[] bKeyValues = { 63, 00, 00, 00 };

One word of caution.  The registry expects a Hex value.  So BIN 63 = HEX 3f, which happens to be the HEX Outlook understands to turn on the fast network setting.  Other values will change the setting in other ways.  For example turning off the “On Fast Networks….” value is BIN 39 = HEX 27.  So the lesson is always use the decimal value in the code.  Windows will automatically convert it to HEX for you.  Use your friendly neighborhood BIN to HEX converter to get the proper values nailed down.

The next piece of code uses the Microsoft.Win32 Library to gain access to the registry.  This section pulls the all the profiles that are under the Windows Messaging Subsystem\profiles hive.  I set an integer value to 0 to assist in looping through all Outlook Profiles on the machine.

RegistryKey rootRegKey = Registry.CurrentUser;
rootRegKey = rootRegKey.OpenSubKey(sKeyPath);
string[] sValueName = rootRegKey.GetValueNames();
int i = 0;

Next, I loop through each profile found and get the key value.  This is critical, because I need to bind to each profile, look for the 13dbb0c8aa05101a9bb000aa002fc45a, the look for 00036623 key and change it’s value to match what I want to set.  Lastly, I Flush the registry key, which is to say, save and close the key.

foreach (string s in sValueName)
            {
                string val = (string)rootRegKey.GetValue(sValueName[i++]);
                RegistryKey subRegKey = Registry.CurrentUser;
                subRegKey = subRegKey.OpenSubKey(sKeyPath + "\\" + val + "\\" + oLPKey, true);
                subRegKey.SetValue(oLOFNKey, bKeyValues, RegistryValueKind.Binary);
                subRegKey.Flush();
                subRegKey.Close();
            }

Voila!  Fin!

Enjoy!

D.

 

1 comment:

  1. Thank you very much : )

    Regard,
    Little Engi

    ReplyDelete