Sdílet prostřednictvím


Can you build one add-in for multiple versions of Office?

This of course is the advantage of using the old "shared add-in" project types – you can build one add-in that targets all versions of all Office apps that support COM add-ins (ie, 2000 onwards). The question is, can you do something similar with VSTO add-ins? The answer is "No, not in any supported way".

If you're a responsible upright citizen, you'll stop reading now.

So, what kind of a cowboy hacker are you anyway? OK then, we'll explore the reasons why it's hard to get this to work, and hopefully it will become obvious why this is not supported – and also why you don't really want to do this.

First, VSTO add-ins only support Office 2003 and later (so, right now, that's Office 2003 and 2007), and we don't support development on a machine with multiple versions of Office. We also don't support mixing PIA versions and Office versions in the same project. This is problematic, especially for ISVs. Technically, it is actually feasible to build a single VSTO add-in that targets both 2003 and 2007, but if you do so you're off into unsupported territory.

If you want to go ahead anyway (and let me say again: this is not supported), there are some useful techniques you can adopt – and some of these are useful even if you do stay with a supported model. First, you need to target the lowest common denominator (Office 2003 in this case), and then write conditional code to use version-specific functionality dependent on which version you're actually running in. While you're doing this, it makes sense to abstract out the version-specific pieces to separate classes, or even to separate DLLs. Separate DLLs are particularly useful – because then, you could reuse these in multiple add-ins – either version-resilient add-ins or version-specific add-ins. You can build each version-specific DLL on a machine with that version of Office and the Office PIAs.

Here's an example.

· (On a machine with Office 2003) I build a DLL called Ui2003, with a set of CommandBar code.

· Then (on a machine with Office 2007), I build a DLL called Ui2007, with a set of Ribbon and Task Pane code.

· Then I build a VSTO Office 2003 Add-in.

· Add references to both the Ui2003 and Ui2007 DLLs.

· Write conditional code that detects the version of the host, and uses either the Ui2003 or Ui2007 functionality.

Of course, one disadvantage of this approach is that your class library DLLs cannot use any of the VSTO wrapper classes – you can only use them in a VSTO project. That means, for one thing, that your Ui2007.dll will have to use the low-level plumbing for customizing the Ribbon, Task Pane and Form Region, instead of the high-level wrappers (and design-time support) provided for VSTO Office 2007 add-ins.

Still reading?

OK, now how do you write the conditional code? The simplest possible approach is to just put a version test in ThisAddIn_Startup, for example:

private void ThisAddIn_Startup(object sender, System.EventArgs e)

{

    if (this.Application.Version == "11.0")

    {

        // 2003-specific code.

    }

    else

    {

        // 2007-specific code.

    }

}

That would work for some simple cases, but don't forget that Office 2007 introduced a new model for extensibility interfaces, where it queries for specific interfaces implemented in the add-in. This means that ThisAddIn_Startup is not the only entrypoint for Office into your code. In VSTO, the new interfaces are supported through the low-level RequestService mechanism. So if you want to support any of these interfaces, your code would have to look something like this:

private void ThisAddIn_Startup(object sender, System.EventArgs e)

{

    if (this.Application.Version == "11.0")

    {

        // 2003-specific code.

    }

}

// 2007-specific code.

protected override object RequestService(Guid serviceGuid)

{

    if (serviceGuid == typeof(Office.IRibbonExtensibility).GUID)

    {

        if (ribbonX == null)

        {

            ribbonX = new RibbonX();

        }

        return ribbonX;

    }

    return base.RequestService(serviceGuid);

}

The RequestService method will only be called if you're running in Office 2007, so it doesn't need to be in a conditional block – but it does begin to make the source code a bit messy. A cleaner approach would be to use partial classes. Using this approach, you'd keep the part of the ThisAddIn class that the project wizard provided fairly uncluttered, and abstract everything (or almost everything) version-specific to 2 new parts of the same partial class. For instance, you'd put something like this in ThisAddIn.cs:

public partial class ThisAddIn

{

    private void ThisAddIn_Startup(object sender, System.EventArgs e)

    {

        if (Application.Version == "11.0")

        {

            Initialize2003Ui();

        }

    }

}

Then, extend the ThisAddIn partial class, with another part, perhaps in a separate file called say ThisAddIn2003.cs. This will use the 2003-specific functionality you abstracted out to Ui2003.dll:

public partial class ThisAddIn

{

    // 2003-specific fields, using Ui2003.dll.

    private Ui2003.CommandBarX commandBarX;

    private void Initialize2003Ui()

    {

        commandBarX = new Ui2003.CommandBarX();

    }

}

…and in ThisAddIn2007.cs, put the 2007-specific pieces of the partial class, using the Ui2007.dll:

public partial class ThisAddIn

{

    // 2007-specific fields, using Ui2007.dll.

    private Ui2007.RibbonX ribbonX;

    protected override object RequestService(Guid serviceGuid)

    {

    if (serviceGuid == typeof(Office.IRibbonExtensibility).GUID)

    {

    if (ribbonX == null)

        {

            ribbonX = new Ui2007.RibbonX();

    }

    return ribbonX;

    }

    return base.RequestService(serviceGuid);

    }

}

Now, when you add a reference to Ui2003.dll to your Office 2003 project, everything is hunky dory, and still within supported territory. However, you will hit a problem when you add a reference to Ui2007.dll. Specifically, the compiler will complain that there are conflicting versions of the core Office PIA in the project, one referenced by the add-in (2003) and one by Ui2007.dll (2007). The only way to fix this is to change the reference in the add-in from the 2003 PIA to the 2007 PIA – and now you're off in unsupported territory.

Also, how does this reconcile with what I said in my previous post, Why is VS development not supported with multiple versions of Office? Office does support running multiple versions of Office on the same machine, although it is discouraged. What's not supported is developing with VS on a machine with multiple versions of Office. Also, as specified in KB 840585 and KB 928091, "The Office 2003 managed code add-ins must be built against the Office 2003 PIAs. The Office 2007 managed code add-ins must be built against the Office 2007 PIAs. Therefore, if you build an add-in solution that you intend to use with several versions of Office, Microsoft recommends that you build a version of your add-in for each version of Office that you intend to support."

The technique I'm describing here does not require multiple versions of Office on the machine. Indeed, it doesn't require any version of Office. It also doesn't necessarily require multiple versions of the PIAs, so long as you build your 2003-specific DLL on a machine with the 2003 PIAs, and you build your 2007-specific DLL (and the ultimate add-in that consumes this DLL) on a machine with the 2007 PIAs. However, it does require you to build a 2003 add-in project which references the 2007 PIAs, and that's not supported .

Even if you can get the thing built on your imaginary dev box, what happens when you want to test it and when you want to deploy it? If you test/deploy on a machine with only Office 2007 and the 2007 PIAs, all is goodness – your 2003 add-in runs with the 2007 PIAs in Office 2007. But, what happens when you test/deploy on a machine with only Office 2003 and the 2003 PIAs? The add-in will fail to load because it's bound to the 2007 PIAs which are not found. OK, so what if you deploy a private copy of the 2007 PIAs? Well, first, you'd have to bind to this private copy at compile time in the first place. Second, it won't help you anyway, because fusion will look in the GAC first – where it will find the 2003 PIAs. So, your 2003 add-in will only work if your 2003 machine has the 2007 PIAs installed in the GAC.

There's another point to consider: 2003 add-ins will be registered in the way Office 2003 expects, and therefore will use the VSTO v2 runtime – even when running in Office 2007. Office 2003 doesn't know any other way to load add-ins. 2007 add-ins, on the other hand, will be registered to take advantage of Office 2007's faster load path, and the enhancements to ClickOnce, and will use the VSTO v3 runtime. The VSTO v3 runtime uses full ClickOnce and streamlined security that does not depend on the version-specific CAS repository. 2003 add-ins must use the VSTO v2 runtime, which uses an emulated ClickOnce, purely CAS-based security, and is dependent on the version-specific CAS repository. Plus, the VSTO v3 runtime is the first version-resilient version – which means your 2007 add-ins are designed to work with the v3 and later runtimes – whereas 2003 add-ins will always require the v2 runtime.

So, do you want to keep building 2003 add-ins, even though you're targeting Office 2007? It seems to me, you really want to move on. Office has moved on – 2007 introduced major changes from previous versions. VSTO has also moved on. Surely, you'd want to take advantage of the new features and enhancements, and build add-ins that specifically target the later version. If you also need to target Office 2003, perhaps you should just bite the bullet – that is, accept that you're going to have a 2003-specific add-in and a separate 2007-specific add-in, instead of trying to munge them together in some way that cannot by definition be optimal for either version. My advice is to build 2 separate add-ins, one for 2003 (which will continue to run in 2007 and later), and one for 2007 (and later).

If you do choose the approved path, and build 2 separate add-ins, there are simple ways to optimize your re-use – more on this later.

Comments

  • Anonymous
    June 25, 2007
    PingBack from http://proofficedev.com/blog/2007/06/26/creating-and-deploying-managed-com-add-ins-with-vsto-2005-se-%e2%80%93-part-ii/
  • Anonymous
    June 28, 2007
    Installing http://www.microsoft.com/downloads/details.aspx?FamilyID=941b3470-3ae9-4aee-8f43-c6bb74cd1466&DisplayLang=en helps resolve some missing reference problems.What do you think about this way?
  • Anonymous
    July 01, 2007
    mclabman - installing the compatibility pack really just installs the file converters. It doesn't install PIAs. So it doesn't change the PIA situation at all.
  • Anonymous
    August 29, 2007
    I build adapter10, adapter11 and adapter12 for my add-in for powerpoint. what I do is create my own interfaces for shapes and slides. then I write the adapter code, but referenced by three projects. I add different version of PIA to those projects. When loading up on connection, I use reflection to load assembly and create the corresponding adapter. I have no problem so far, and I do think shared add-in is more convenient to use compared with VSTO and Add-in Express.
  • Anonymous
    November 09, 2007
    Hi Andrew,You wrote:"My advice is to build 2 separate add-ins, one for 2003 (which will continue to run in 2007 and later)..."From this, I infer that running a shimmed COM add-in (and/or a shimmed Automation add-in) which is compiled against the Office 2003 PIAs is supported with Excel 2007.  Is that correct?  Or should it really be rebuilt using references to the Office 12 PIAs before deployment with Excel 2007?I have such an add-in (COM add-in and Automation add-in (both shimmed) and a group of C# COM objects which are exposed for use in VBA).  This all appears to work fine when deployed on a PC with Excel 2007, where it obviously loads the Office 2007 PIAs rather than the Office 2003 PIAs against which it was built.  I'd just like to know whether this is supported.I'm investigating developing a new VSTO 2005 SE add-in to make use of the ribbon such that I'd no longer add to the menus as the Excel 2003 COM Add-in currently does.  But I've run into some problems getting this VSTO add-in to load the Automation add-in for me (which is what the COM add-in does).  I've also had some issues with exposing the C# COM objects to VBA from the VSTO add-in.  Now all these issues may be soluble, but since my existing Excel 2003 add-ins appear to work fine, I have been thinking about writing a VSTO 2005 SE add-in which would provide the ribbon features I need and deploying the existing Excel 2003 add-ins along side it (with conditional code to prevent additions to the menu structure when called from Excel 2007).Thanks,Mike
  • Anonymous
    November 09, 2007
    It appears that my question above is largely answered by your previous blog entry: http://blogs.msdn.com/andreww/archive/2007/06/08/why-is-vs-development-not-supported-with-multiple-versions-of-office.aspx:)I'd still be interested to hear your thoughts on whether it's a good idea to make use of the ribbon by writing a new VSTO 2005 SE add-in which then calls into my existing COM add-in (for dialogs; the VBA COM objects; etc.)and my existing Automation add-in (for UDFs).  Or, should I be chasing down the issues that have so far prevented me from loading my Automation Add-in from the VSTO 2005 SE add-in.Thanks,Mike
  • Anonymous
    November 25, 2007
    I created a shared add-in for Outlook. I want it make workable in both 2003 and 2007. Object library 12.0 is not supporting outlook 2003. so I removed object library12.0 and do with libray 11.0. But object library 11.0 not support IRibbonExtensibility. So i want to create seprate dll for IRibbonExtensibility, and it add to my project. Can you help me for creating  IRibbonExtensibility dll in c#
  • Anonymous
    March 20, 2008
    Theoretically, you can develop an add-in for multiple versions of Microsoft Office by catering to the
  • Anonymous
    May 26, 2008
    One of the common questions I get asked when I do sessions on VSTO / OBA development is "how can
  • Anonymous
    June 03, 2008
    In a previous post , I discussed how you could build an add-in for multiple versions of Office, and explained
  • Anonymous
    August 11, 2008
    Hi Andrew can u tell me that can i create add in Outlook2002 using Vs2005 VSTO
  • Anonymous
    August 12, 2008
    wasim - VSTO does not support add-ins for versions of Office prior to 2003. If you want to build an add-in for Outlook 2002, you should use the shared add-in projects, as described here: http://msdn.microsoft.com/en-us/library/aa155703.aspx.
  • Anonymous
    September 09, 2008
    Continuing on from my earlier posts on building add-ins for multiple versions of Office , avoiding the
  • Anonymous
    September 25, 2008
    Originurl:http://blogs.msdn.com/andreww/archive/2007/06/15/can-you-build-one-add-in-for-multiple-v...
  • Anonymous
    September 25, 2008
    This of course is the advantage of using the old
  • Anonymous
    February 24, 2009
    Developed an office 2003 automation application in a machine with office 2003. It works well in a client machine with just office 2003. But fails in a client machine with Office 2003 with office 2007 compatibility pack installed. Any pointers to resolve this issue.
  • Anonymous
    February 24, 2009
    Ranjeev - the compatibility pack does not change the Office 2003 object model, so there should be no differences. You don't say anything specific about what is actually failing - if it is failing at some OM call, you need to debug into your code to see what the problem is. If it is failing to instantiate the Office application objects, then there might be a registration problem. In any case, you need to provide more information.
  • Anonymous
    March 02, 2009
    Andreww. Thanks fo your valuable reply. The issues was it was not able find the Microsoft Office dlls. The Exception it thrown wasSystem.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Office.Interop.Word, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' or one of its dependencies. The system cannot find the file specified.File name: 'Microsoft.Office.Interop.Word, Version=11.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'This was temperory fixed by doing copy local true for the assemblies this is against the microsoft recommendations for a Shared library for GAC. Please advise on this.Other than this issue there is one more issue where the application is not working in a highly secured environment. I think this is a security related issue.Can you please check the following thread started by me regarding this issue.http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/ea864a09-2fb9-4945-8b61-03fa06aff512Thanks,-Rajeev
  • Anonymous
    March 03, 2009
    Rajeev - as Tim points out in that forum thread, and as I've pointed out in the referenced blog posts, developing VSTO add-ins explicitly for multiple versions of Office is not supported and not recommended. As you can see, and as explained in the posts, you will hit a number of version-conflict problems. The VSTO model is strictly versioned.That said, if you build for the lowest common denominator, the add-in should continue to work unchanged in later versions of Office - this is also part of the VSTO model.The workarounds I describe in my posts are just that - workarounds. They are not supported mechanisms, and are probably only useful for advanced developers who are willing to accept the lack of support.
  • Anonymous
    March 03, 2009
    Thanks for your inputs and your time. It really helped to understand much about the VSTO model andthe way it works.Thanks,Rajeev
  • Anonymous
    May 22, 2009
    Ohhh you HAD to tell me this now!!  We have an add-in, developed years ago for 2003.  Its been running on 2007, until something caused it to "blurf" and not load on one of the product QA's machine (which has both office 2003 and office 2007 installed).  So, now you're telling us we have to build two versions, one for 2003 and one for 2007?   Akk, pain, misery...    And our target customers have a wide range of MS Office versions installed.  Imagine telling a world wide bank "Excuse me, but you MUST upgrade all 111,452 desktops, all over the world, to use the same version of office..."
  • Anonymous
    May 22, 2009
    Mike - the technique described in this post is for the case where you want to take advantage of different features available in multiple versions of Office.If all you want to do is build an add-in for one version, and have that add-in continue to work for later versions - then, you don't have to do anything. Office takes great pains to maintain backwards compatibility, so an add-in built for Office 2003 should just continue to work the same way as always in Office 2007 and later. This has always been the case, since COM add-ins were first introduced in Office 2000.
  • Anonymous
    May 22, 2009
    The comment has been removed
  • Anonymous
    May 22, 2009
    Mike - I understand that many organizations cannot move on to the latest version in the short term. My point is that in this scenario, you don't have to do anything. Your 2003 add-ins should just work in 2007.You would only want to move on to building 2007 add-ins if your customers moved to 2007 AND if you want to take advantage of new features in 2007.You only have the problem of targeting multiple versions if your customer has multiple versions deployed AND your add-in needs to work in multiple versions AND you need to do different things depending on which version you're running in. In this scenario, you're targeting the lowest common denominator, but at the same time building in forward compatibility. Fortunately, this is not a common scenario.Also, just to clarify, this affects all technologies - it doesn't matter if you're using VSTO or not.
  • Anonymous
    May 22, 2009
    Thanks Andrew.    Great article as usual.I just wanted to clarify one thing:   If the add-in is developed/built on a build machine with Office 2003 PIA's, does that mean that Office 2003 PIA's need to be installed on the deployment machine, even if the customer is using Office 2007?    
  • Anonymous
    May 22, 2009
    Mike - if you're building on a machine with Office 2003, I assume you're only using 2003 features. Later versions of Office are generally supersets - that is they don't generally remove features, but simply add more features. So any 2003 features should all still be present and correct in 2007. Which means, you don't need the 2003 PIAs on the 2007 machine, as the 2007 PIAs should be a superset of the 2003 PIAs.
  • Anonymous
    May 27, 2009
    Hi Andrew,      As luck would have it, the add-in stopped loading in Excel 2007 on one machine. We didn't make any changes to the add_in, its still an office 2003 COM addin (built in C# with Dev Studio 2008 + SP1) it loads in Excel 2003 on that same machine. We've tried everythying, uninstalling/reinstalled the add-in, excel 2007, the PIA's.  When Excel starts, the COM add-in is listed in the Excel configuration tab, but its listed as disabled.  We check the checkbox, restart, it doesnt load and its still disabled. We checked the loadBehavior registry key, its correct, set to 3, never changes.  We checked the trust center, nothing bad there.  Any suggestions greatly appreciated.Mike
  • Anonymous
    May 27, 2009
    The comment has been removed
  • Anonymous
    May 27, 2009
    Andrew,    Thanks, that did it!  
  • Anonymous
    June 12, 2009
    Is it possible to install seperate add-ins dlls , one for 2003 and another for 2007 on a a machine where only office 2003 is available so as when user upgrade to office 2007 it picks up add-in related to 2007?ThanksAnurag
  • Anonymous
    June 12, 2009
    Anurag - not, Office does not support versioned add-in installs. Office will pick up all registered add-ins, regardless of version.