First, the Office client apps are COM-based. Normal COM activation relies on the registry. COM registration is a “last one wins” model. That is, you can have multiple versions of a COM server, object, interface or type library on a machine at the same time. Also, all of these entities can be registered. However, multiple versions can (and usually do) use the same identifiers, so whichever version was registered last overwrites any previous one. Also, when it comes time to activate the object, only the last one registered will be activated. COM identity at runtime depends on an object’s implementation of QueryInterface, but COM identity at the point of discovery depends on GUIDs. GUIDs are used because they provide a guaranteed (for all practical purposes) unique identifier (surprise).
As soon as you put multiple versions of a COM server/object/interface/typelib onto the same machine, you introduce scope for variability. That is, although COM activation will ensure that the GUID-identified object gets used at the point of activation, you’ve set up the environment such that the object that this GUID identifies can change unpredictably over time – even short periods of time. This is one of the many reasons why it is very difficult to successfully develop solutions on a machine with multiple versions of Office – and one of the reasons we do not support this. But wait, how can this be? Surely a COM interface never versions? That’s true, but, first, Office interfaces are not pure COM interfaces – they’re automation interfaces, which are allowed to version (while retaining the same GUID). Second, the objects that implement the interfaces are obviously allowed to version, as are the typelibs that describe them.
Consider the scenario. You’ve installed Excel 2003 on your dev box, including the relevant Office 2003 PIAs. You create an Excel 2003 add-in. The project references the Excel 2003 PIAs. At runtime (including F5 from VS), Excel 2003 is launched, and it loads your solution which is bound against the Excel 2003 PIAs, which are also used at runtime. All is good.
Now, you install Excel 2007, keeping Excel 2003 on the machine (and at this point you’ve gone off the map into unsupported territory). At the same time, you install the Excel 2007 PIAs. So, the COM registration for all the objects, interfaces and typelibs now points to the 2007 versions. Plus, the Office 2007 PIAs include fusion binding redirect policies so that references to the Office 2003 PIAs are redirected to use the 2007 PIAs at runtime. If you explicitly launch Excel 2007 (or if you double-click an XLS, XLT, XLSX etc file – which are all now registered against Excel 2007), it will load your add-in and the Excel 2007 PIAs. This is close to the supported scenario where a user upgrades from Excel 2003 to Excel 2007 and does not retain the old version. In the supported scenario, we expect the add-in (originally built against 2003) to continue to work with Excel 2007 and the Excel 2007 PIAs (barring any breaking changes that Office might introduce between one version and the next). So, the normal case should just work.
However, on this imaginary machine we’ve retained the old version. So, what happens if you run Excel 2003 explicitly from the Start menu or from %ProgramFiles%\Office11\Excel.exe directly. Or indeed, if you press F5 within VS, which (on an Excel 2003 project) will also attempt to run Excel 2003 explicitly? Excel 2003 will run, and it will load your add-in, but it will be using the Excel 2007 PIAs. If there are no breaking changes between the 2003 and 2007 OMs (and therefore the PIAs), this should probably work ok – but if there are breaking changes, you’re hosed.
Also, by default, when you add a reference to a PIA, this goes through COM registration. So, regardless of which version of the PIA you select from the Add Reference dialog, you’ll actually end up with a reference to the last version that was registered. This is standard COM behavior, by design.
Now, let’s say that on our imaginary dev box with multiple versions of Excel, we now create a new Excel 2003 project. This will be created ok, but the PIA references will be references to the last registered Excel 2007 PIAs. Or alternatively, if we delete the Excel and Office PIA references, and use the Add Reference dialog to add a reference to the Excel 2003 and Office 2003 PIAs. Even if you explicitly select the Excel 11.0 Object Library, because of COM registration, you’ll end up with a reference to the Excel 2007 (12.0) and Office 2007 PIAs. Either way, you’ll get the last registered PIAs. So what happens if you go ahead and build this project and try to run it? As before, if you explicitly run Excel 2007, everything loads and works just fine. As before, if you try to run Excel 2003, it runs with the Excel 2007 PIAs.
So, if you really insist on having multiple versions of the PIAs on the box (and I can’t think of a good reason, and we certainly don’t support this scenario), then you can workaround the problem by simply adding a reference to the specific PIA you want by its path not by its COM registration. Note, if you do this, you should not use the path to the PIA in the GAC. Instead, you should copy the relevant PIAs to some known location and reference them there. So, let’s say we go back to our Excel 2003 project, and change the PIA references in this way. We could explicitly set references to the (path to the) Excel 2003 and Office 2003 PIAs. This will build ok, and you’ll end up with an assembly whose metadata specifies that it should use the 2003 PIAs. If you then deploy this to an end-user machine which only has 2003, you’re good. However, if you try to run it on your dev box, it will again use the 2007 PIAs – because that’s the version that was registered last. So, fixing the PIA references only ensures you build the correct assembly that will work on the end-user’s machine which has the matching version of the host app. It does not help you on the dev box. If you have multiple versions on the dev box, all bets are off.
Also consider that a machine with multiple Office versions could have all kinds of bizarre permutations. What if you install 2003 then install 2007 then uninstall the 2007 PIAs but not the 2007 apps; or you re-install the 2003 PIAs after installing the 2007 apps, etc, etc. Or, you could register say Excel 2003, plus say the 2007 version of the main Office dll, plus Excel 2007 PIAs, plus the 2003 version of the main Office PIAs, and so on. You can see how this rapidly produces a meaningless dev environment – you’d never be sure which permutation of versions you’re running against, and most permutations would simply not be valid in a real end-user environment. You might think you can be careful to ensure you don’t end up with such silly registration permutations, but factor in that both Office 2003 and Office 2007 and their many sub-components will auto-repair themselves at arbitrary times, and that related patches may also be applied at arbitrary times (perhaps pushed down by corporate IT), and so on. You can begin to understand why we do not support this scenario.
Now consider doc-level customizations. This is even more interesting, because we host Excel and Word objects within the VS IDE as design surfaces, using OLE inplace activation. This, of course, relies on COM registration. So, on our imaginary multi-version dev box, if you try to create an Excel 2003 doc-level customization, we’ll end up hosting Excel 2007, and the PIA references will again be set to 2007 versions. So, for one thing, all the intellisense and autocomplete support will be specific to the 2007 versions of the OMs. This will inevitably encourage you to use method parameters or whole features of Excel/Office that are not available in the 2003 version – because the design-time support considers this valid, and the solution will build correctly (against the 2007 PIAs).
If you go ahead anyway, and then try to run the solution, by default VS will launch Excel 2003 (because that was the target version you specified when you created the project), and it will load your customization, but with the Excel and Office 2007 PIAs. Now, your code will fail in arbitrary places because you’re using features that are simply not present – or are present with different signatures or semantics – in the running version. Plus, of course, running an app with a later version of the PIAs is strictly not supported.
You can see that there are many good reasons why we do not support developing on a machine with multiple versions of Office. You can also make the case that this is not a sensible dev environment, it is extremely difficult to get consistent behavior, it is likely impossible to guarantee that the environment stays consistent for any length of time, and you’re pretty much guaranteed to have a dev environment that cannot match any sensible end-user environment, which therefore invalidates any testing you might do.