Welcome to MSDN Blogs Sign in | Join | Help

Andrew Whitechapel

Visual Studio, Office and other Nonsense
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.

Posted: Friday, June 15, 2007 9:16 PM by andreww

Comments

mclabman said:

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?

# June 29, 2007 1:50 AM

andreww said:

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.

# July 1, 2007 5:54 PM

taowen said:

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.

# August 29, 2007 8:38 AM

MikeI said:

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

# November 9, 2007 10:46 AM

MikeI said:

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

# November 9, 2007 11:35 AM

Mujeeb said:

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 library

12.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#

# November 26, 2007 5:19 AM

Visual Studio 2008: Microsoft Visual Studio Tools for Office said:

Theoretically, you can develop an add-in for multiple versions of Microsoft Office by catering to the

# March 20, 2008 4:07 PM

Andrew Coates ::: MSFT said:

One of the common questions I get asked when I do sessions on VSTO / OBA development is "how can

# May 27, 2008 4:22 AM

Andrew Whitechapel said:

In a previous post , I discussed how you could build an add-in for multiple versions of Office, and explained

# June 3, 2008 12:48 PM

wasim said:

Hi Andrew can u tell me that can i create add in Outlook2002 using Vs2005 VSTO

# August 12, 2008 5:52 AM

andreww said:

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.

# August 12, 2008 7:28 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker