I’m not a big believer in testing on the same machine you build on – it’s a good way to inadvertently design bugs into your code that only appear when your code is deployed. So I keep a build machine, where I do all my coding/building, and I run my projects on other machines – usually a VM. Usually, this does not cause me a problem. Yesterday, while working on a Form Regions issue, I encountered a dependency the VSTO folks built into their build process, and wanted to share the workaround.
We begin by creating a C# Outlook 2007 Add-In project in Visual Studio 2008, which builds just fine. Since Outlook isn’t installed, we use the Publish wizard to publish the add-in to a share, and from there we can install it on our test machine. So far so good. Then we add an Outlook Form Region. Before we do any customization on it, we test build, and get this:
------ Build started: Project: MyFormRegion, Configuration: Debug Any CPU ------
<very long build command cut for clarity>
Compile complete -- 0 errors, 0 warnings
MyFormRegion -> C:\projects\MyFormRegion\bin\Debug\MyFormRegion.dll
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v9.0\OfficeTools\Microsoft.VisualStudio.Tools.Office.Office2007.targets(154,9): error :
Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
Done building project "MyFormRegion.csproj" -- FAILED.
========== Build: 0 succeeded or up-to-date, 1 failed, 0 skipped ==========
This much reviled error message gets a lot of traffic on the interwebs, but there’s not much helpful information about what it means. That is, until I include the term “Form region” in my search. That cuts the chatter to one hit, a discussion between a developer who uses an environment similar to mine, and Daniel Molina, one of our VSTO developers. Between the two of them, they figured out the failure occurs when we try to use reflection during the build process. They figured out that installing the Outlook PIA into the GAC would fix the problem. I tried it here:
C:\Program Files\Microsoft.NET\SDK\v2.0 64bit\Bin>gacutil.exe /i "C:\Program Files (x86)\Microsoft Visual Studio 9.0\Vis
ual Studio Tools for Office\PIA\Office12\Microsoft.Office.Interop.Outlook.dll"
Microsoft (R) .NET Global Assembly Cache Utility. Version 2.0.50727.42
Copyright (c) Microsoft Corporation. All rights reserved.
Assembly successfully added to the cache
I had another issue recently where MAPI wasn’t able to connect via NSPI to the Exchange server or DC. The customer had a CDO application, running on an Exchange 2007 server on Windows 2008, using the Exchange MAPI download. In other environments, the application worked, but in this one environment, they were getting MAPI_E_LOGON_FAILED. This is the symptom and the sort of environment where the IPv6 issue occur, but they were running Exchange 2007 SP1 Rollup 5, where the IPv6 issue is supposed to be fixed. Additionally, the customer insisted IPv6 was not even present in the environment. Just to be sure, I had them get an ipconfig and it showed only IPv4 was in use, so I dismissed IPv6 as a possibility for a while.
Debugging their application as it tried to connect showed that NSPIBind to the Exchange server was succeeding, but no data was being returned. So we debugged the Exchange System Attendant, which hosts DSProxy, the component that handles the NSPIBind call. This component is supposed to take the bind request and proxy it over to the DC. I could find where DSProxy received the NSPIBind request, but when it consulted it’s list of available DCs, it found the list was empty. That’s when I noticed something – the NSPIBind request had come in over IPv6, which was supposed to be disabled! The list DSProxy consulted was of DCs that supported IPv6, and none did. Had the request come in over IPv4, it would have consulted a list that had active DCs in it.
So – we went back to the Exchange server and took a closer look. Network properties showed IPv6 was available, but unchecked:
When we looked in the registry, however, we got a different story:
IPv6 wasn’t disabled. As noted on other sites, in order to truly disable IPv6 you have to set the DisabledComponents value under the HKLM\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters key to something like 0xFF. If you don’t do this, IPv6 is still available.
We set this reg value on the customer’s Exchange server, rebooted for it to take effect, and now their MAPI application works like a charm.
In short, the problem happened here because IPv6 had been only partially disabled in the customer’s environment. If you’re running Exchange 2007 and wish to disable IPv6 in your environment without breaking MAPI, you must follow these steps on your Exchange server (swiped from the Ehlo blog post):
[Edit - 2/2/2010] According to http://support.microsoft.com/kb/929852, we should set DisabledComponents to 0xFFFFFFFF if we really, really want to disable IPv6.
The January 2009 Release (build 126.96.36.1991) is live: http://www.codeplex.com/MFCMAPI
Mostly bug fixes this time around. Most prominent was the inability to add a property to an item. Also, the Property Tag Editor needed some serious TLC.
Here's a change list - see the Issue Tracker on Codeplex for more details, or look at the code: