This documentation is archived and is not being maintained.

Retargeting a Word 2007 Add-In that uses Smart Tags from .NET 3.5 to .NET 4.0

Office 2007

Office Visual How To
Summary: Given a Word 2007 add-in including one or more smart tags targeting the Microsoft .NET Framework 3.5, you may want to change the add-in to target .NET Framework 4.0 so that you can take advantage of new framework features. Changing the target version of the .NET Framework for a Word add-in from .NET Framework 3.5 to .NET Framework 4.0 is easy, but requires specific steps.

Applies to:    2007 Microsoft Office system | Microsoft Office Word 2007 | Visual Studio 2010

Published:   August 2010

Provided by:   Ken Getz, MVP, MCW Technologies, LLC


Scenario: You created an add-in for Microsoft Office Word 2007 that includes a custom smart tag and a Ribbon customization. You built it using Microsoft Visual Studio 2008 for the 2007 Microsoft Office system and the Microsoft .NET Framework 3.5. Now, given Microsoft Visual Studio 2010 and the .NET Framework 2010, you want to update your add-in to target the new version of the Microsoft .NET Framework. It's easy to modify the target version of .NET, but you find that doing so has caused your add-in not to compile. You need to modify the code slightly to use the new interface-based features in the Office Extensions for the .NET Framework 4.0.

The sample that is included with this article includes a working Word 2007 add-in, created by using Visual Studio 2008. This add-in targets the .NET Framework 3.5, and it includes two features. The add-in provides a custom smart tag which recognizes temperatures in Fahrenheit or Celsius, and offers the option to convert to the other scale, shown in Figure 1. The Ribbon customization, shown in Figure 2, lets you enter a temperature value, set its scale, and then insert the temperature into the document. You may find the internal code for the add-in to be of interest, but it's not the focus of this article. Instead, this article focuses on migrating this add-in so that it targets the .NET Framework 4.0.

Targeting the .NET Framework 4.0 lets you take advantage of the fact that the Office Extensions for the .NET Framework 4.0 use a runtime that is version-resilient, based on interfaces instead of classes. Combined with type embedding, this makes your solution much less dependent on the version of Office installed on end user computers. For more information about the benefits of upgrading your add-in so that it targets the .NET Framework 4.0, see the links in the Explore It section.

Figure 1. The smart tag helps convert temperatures from one scale to another

Convert Temperatures
Figure 2. The Ribbon customization allows you to insert a formatted temperature value

Ribbon Customization


Code It

Download the sample code

Follow these steps to convert the add-in so that it targets the .NET Framework 4.0.

To Set the Target Version

  1. In Visual Studio 2010, in the Solution Explorer window, right-click the project node and select Properties from the context menu.

  2. In the Properties window, for Microsoft Visual Basic, select the Compile tab and then the Advanced Compile Options button. For both Microsoft Visual Basic and Microsoft C#, set the Target framework property to .NET Framework 4.0 Client Profile. (Note that the Client Profile option sets the project up for client-side use, and includes references to fewer assemblies than would be added by selecting the .NET Framework 4.0 option.) When prompted to close and re-open the project so that Visual Studio can change the Target Framework, click Yes.

  3. Save and compile the project: You will find that the project, which originally compiled and ran fine, now returns many errors that you must fix.

To Fix the SmartTag

  1. In the Solution Explorer window, double-click TemperatureSmartTag.vb or .cs, displaying the code in the Code Editor.

  2. In .NET Framework 4.0 projects, a smart tag implements the ISmartTagExtension interface, instead of inheriting from the SmartTag class: In the Code Editor, change the declaration of the TemperatureSmartTag class so that it implements the Word.ISmartTagExtension interface, instead of inheriting from the SmartTag class. The class declaration should look like the following code.

    class TemperatureSmartTag : Word.ISmartTagExtension
  3. In Visual Basic, press Enter to have Visual Studio create the necessary procedure stubs required by the interface. In C#, right-click the interface name, and select Implement Interface, and then Implement Interface (again) to generate the stubs.

  4. Within the class, add a declaration for an instance of the Word.SmartTag class; you will use this instance to represent the actual smart tag.

    private Word.SmartTag smartTagDemo = null;
  5. Find the ExtensionBase property, and modify it so that it returns the smartTagDemo variable.

    public object ExtensionBase
      get { return smartTagDemo; }
  6. Because the smart tag class now implements an interface, instead of inheriting from a class, you must add code to create an instance of the smart tag. Modify the class' constructor so that it calls the Globals.Factory.CreateSmartTag method, which returns the smart tag object that you need. In Visual Basic, replace the call to MyBase.New. In C#, replace the call to the base method.

    this.smartTagDemo = Globals.Factory.CreateSmartTag(  
    "", "Temperature", this);
  7. In the constructor, replace code that calls Expressions.Add so that it calls the same method on the smartTagDemo object.

    smartTagDemo.Expressions.Add(new Regex(
  8. Modify the code that creates the Word.Action instances--rather than creating the object yourself, call the appropriate factory method to create the object.

    temperatureAction = Globals.Factory.CreateAction("Convert");
  9. Modify the code that sets the class' Action property so that it sets the Action property of smartTagDemo, instead:

    smartTagDemo.Actions = new Word.Action[] { temperatureAction };
  10. Add a Base property that returns the smartTagDemo variable:

    public Word.SmartTag Base
      get { return smartTagDemo; }
  11. In C#, remove the code from the Recognize method. This code, provided by the Visual Studio template when you implemented the interface, throws an exception because the method hasn't yet been implemented. Because the current example does not require a Recognize method to do its job, the code should do nothing at all:

    public void Recognize(
      string text, 
      Microsoft.Office.Interop.SmartTag.ISmartTagRecognizerSite site, 
      Microsoft.Office.Interop.SmartTag.ISmartTagTokenList tokenList, 
      SmartTagRecognizeContext context)
      // Do nothing at all.

In projects that target the .NET Framework 3.5, code in the add-in class calls the GetVstoObject method of the host document, retrieving the extended object that adds managed functionality to the host document. In projects that target the .NET Framework 4.0, code must instead call the Globals.Factory.GetVstoObject method, passing in a reference to the native Word or Excel object that you want to extend. Therefore, follow these steps to fix up the call to GetVstoObject.

To Fix up ThisAddIn

  1. In the Solution Explorer window, double-click ThisAddIn.vb or .cs, loading it into the Code Editor.

  2. Find the code that calls the GetVstoObject method, and replace the line with the following code.

    var vstoDocument = Globals.Factory.GetVstoObject(interopDocument);
  3. Because the VstoSmartTags.Add method requires an actual smart tag instance, modify the call to VstoSmartTags.Add so that it passes in the Base property of the new smart tag that the code creates.

    vstoDocument.VstoSmartTags.Add(new TemperatureSmartTag().Base);

To Fix up the Ribbon Customization

  1. In the Solution Explorer window, expand Ribbon1.vb or .cs, and double-click Ribbon1.Designer.vb or .cs to open it in the Code Editor. (If you cannot expand Ribbon1, select Project, and then Show All Files.)

  2. Modify the Ribbon1 class so that it inherits from the RibbonBase class, as opposed to the OfficeRibbon class.

  3. Modify the class' constructor so that it calls the Globals.Factory.GetRibbonFactory method in the base class:

    public Ribbon1():
  4. Because all the elements that you place on Ribbon customizations are now based on interfaces, rather than classes, you must call the appropriate factory method to hand you an instance of the corresponding Ribbon control. In your own code, you will have to find any place in which you create an instance of a control. In the sample, in Ribbon1.Designer.vb or .cs, find the InitializeComponent procedure. (In C#, expand the Component Designer generated code block first.)

  5. Replace the lines in the sample that create instances of controls with the following code, which calls the correct factory method for each control type.

    Microsoft.Office.Tools.Ribbon.RibbonDropDownItem ribbonDropDownItem1 = 
    Microsoft.Office.Tools.Ribbon.RibbonDropDownItem ribbonDropDownItem2 = 
    this.TabCustom = this.Factory.CreateRibbonTab();
    this.temperatureGroup = this.Factory.CreateRibbonGroup();
    this.TemperatureEditBox = this.Factory.CreateRibbonEditBox();
    this.ScaleDropDown = this.Factory.CreateRibbonDropDown();
    this.InsertButton = this.Factory.CreateRibbonButton();
  6. Find the ThisRibbonCollection class, and modify the class so that it no longer inherits from the RibbonReadOnlyCollection class.

  7. In C#, you must replace all event handler declarations with new, generic delegates. The simplest way to do this is to create a new blank line, type the event name, type the += operator, and allow the editor to create the new delegate instance. In the sample, find the line of code that sets up the this.Load event handler, create a blank line, and let the editor generate the new event handler hookup for you. Delete the original when you're done. For example, the new code for the Load event looks like the following code.

    this.Load +=new Microsoft.Office.Tools.Ribbon.RibbonUIEventHandler(

If you have followed the steps carefully, you should now be able to compile and run the modified version of the sample Word add-in.

Read It

It's important to find any code that instantiates Ribbon controls outside the designer class, and call the appropriate factory method to create the instance instead. In the Ribbon class itself, you can simply call Factory.Create<ControlType>. In other classes, you can use the Globals.Factory instance, calling the Create<ControlType> method. There are no instances of this need in the sample project, but there may be in your own projects.

The example you have seen here includes many of the issues that you will encounter when updating your own add-ins to target the .NET Framework 4.0, but clearly, you will have other issues as well. Review the documents listed in the Explore It section--you will find complete documentation on the kinds of issues you're likely to encounter, as well as full documentation on the new factory methods and other important information.

You may find it simpler to start from scratch. That is, it may be easier to re-create the user interface for your Ribbon customizations, allowing the Visual Studio 2010 designer to create the appropriate code for you. Then, you can copy over your own code, and fix up any minor issues that you find. For a large and complex customization, this may be a simpler solution.

See It

Watch the Video

Watch the Video

Video Length: 08:59

File Size: 12.8 MB WMV

Explore It

About the Author

Ken Getz (MVP) is a developer, writer, and trainer, working as a senior consultant with MCW Technologies, LLC. In addition to writing hundreds of technical articles over the past fifteen years, he is lead courseware author for AppDev ( Ken has co-authored several technical books for developers, including the best-selling ASP.NET Developer's Jumpstart, Access Developer's Handbook series, and VBA Developer's Handbook series. Ken is a member of the INETA Speakers Bureau, and speaks regularly at a large number of industry events, including 1105 Media's VSLive, and Microsoft's Tech-Ed.