VSTO Add-In : Load Error [Outlook and other Office Applications]

A common issue faced by VSTO Add-in developers is the failure to load the add-in when your Office application starts. For example, the following message appears in COM Add-in window of Outlook 2003 if it is unable to load your add-in:

“Not Loaded. A runtime error occurred during the loading of the COM Add-in”

There can be many reasons for this behavior and requires your step by step verification of each one. Note that the message descriptions given below are specific for Outlook 2003 and Outlook 2007 and may vary for other office applications.

1. Enable the Add-in (if it is found under disabled items)

Outlook 2003:

  • Go to Help –> About Microsoft Office
  • Click on “Disabled Items”
  • Select your add-in (if found there) and click enable
  • Close and start Outlook

Outlook 2007:

Use the following steps to access Disabled items:

  • Go to Help—> Disabled Items

OR

  • On the Tools menu, click Trust Center.
  • In the Navigation Pane, click Add-ins.
  • In the Manage list, select Disabled Items, and then click Go.

2. Enable the Add-in from  COM Add-in Window

Outlook 2003:

  • Go to Tools –> Options –> Others –> Advanced Options –> COM Add-ins
  • Select and Check your add-in (if found there as unchecked) and click OK
  • Your outlook plug-in should load now, if not go back to COM Add-ins window and see if there are any error messages.

Outlook 2007:

Use the following steps to access Disabled items:

  • On the Tools menu, click Trust Center.
  • In the Navigation Pane, click Add-ins.
  • In the Manage list, select COM Add-ins, and then click Go.
  • Select and Check your add-in (if found there as unchecked) and click OK

3. Check registry settings

  • Go to : HKEY_LOCAL_MACHINE\Software\Microsoft\Office\Outlook\Addins\<AddIn Name> (Or HKCU equivalent)
  • Check the loadbehavior key value. If it is set to 2, change to 3 and start your Outlook
  • If the Add-in does not load, go back to registry and check the loadbehavior value. You may notice that the value is changed back to 2 (indicating the problem while loading your plug-in) and we should go to next steps.

4. Check CAS (Code Access Security) permissions for the code group

Your Add-in assemblies code group should be given “FullTrust” permission. You can verify the current permission levels using one of the following.

  • CASPOL.EXE : Use caspol tool to query the code groups and permission levels
  • Use .NET Framework Configuration Tool (mscorcfg.msc)

If FullTrust permissions are not given, use caspol.exe to grant FullTrust to the add-in assemblies

Example: <From Visual Studio Command Prompt>

caspol -u -ag All_Code –url  “C:\<FolderName>\<FolderName>\*” FullTrust -n "<Name>" –d "<Description>"

More details on CAS is out of scope for this post. You can refer this for detailed instructions: How to: Grant Permissions to Folders and Assemblies

5. Check Primary Interop Assemblies (PIA) are installed correct

Verify whether Primary Interop Assemblies [for Office 2003 or Office 2007 depending upon your version of MS Office] installed correctly on your machine. To check this, go to GAC (%systemroot%\assembly) and look for assemblies named Microsoft.Office.Interop.*  and their versions.

If not installed, get it downloaded from the following URLs:

6. Add Custom Logging

Place the code in the Startup event to log exception details to  System Event Log which can give you if the exceptions are occurred during the load event.

<To be updated>

The above steps will help to identify/fix the load error. If you do not find the solution for your error get more help from this Microsoft Support Link to troubleshoot.

Advertisements

Steps to develop an AddIn using Managed AddIn Framework (MAF)

I had blogged earlier about Managed AddIn Framework and the resources to learn the basics. Making use of System.AddIn framework features can appear complex for beginners. In this example we develop a host application and AddIn using Managed AddIn Framework.

Source Code: You can download the source code for this example below.

 Source Code 

The diagram below demonstrates how we are going to implement each component in the Managed AddIn Framework in our sample application.

clip_image001

When you activate an Addin from host, you can load the Addin in its own application domain or in an existing application domain or even in a new process separate from host’s process.

Step -1 – HostView

Create a solution with the following solution folders. Create a class library project named HostView under the Pipeline solution folder.

It is important to set the project settings. For HostView, change the output path to ..\output\ (Visual Studio default will be \bin\debug or \bin\release)

The HostView is an abstract class with methods corresponding to the methods exposed by the Addin. In this example I go for a simple method which returns the sum of two integer numbers.

namespace Demo.HostView
{
    public abstract class HostView
    {
        public abstract int ComputeSum(int a, int b);
    }
}

Step -2 – Create Host Application

Create a Windows Application project named SampleHost under the HostApplication solution folder.

clip_image003 

  1. Change the output path to ..\output\

  2. Add reference to assemblies System.AddIn and System.AddIn.Contract

  3. Add reference to project HostView

The host application UI is given below. It aims to load our addin and use it for computing the sum of numbers supplied from the host application.

clip_image005

Add the following code in the Host to load the AddIn

Collection<AddInToken> _addinTokens;
Collection<HostView> _addinList = new Collection<HostView>();
HostView calcAddin;

private void btn_Load_Click(object sender, EventArgs e)
{
    LoadAddins();
}

public void LoadAddins()
{
    // Set root directory for finding Add-ins
    string addinRoot = Environment.CurrentDirectory;

    // Rebuild the add-ins and pipeline components 
    AddInStore.Rebuild(addinRoot);

    // Find add-ins of type HostView
    _addinTokens = AddInStore.FindAddIns(typeof(HostView), addinRoot);

    foreach (AddInToken addinToken in _addinTokens)
    {
        // Activate the add-in
        _addinList.Add(
            addinToken.Activate<HostView>(AddInSecurityLevel.Internet));

        // Display Addin-Details
        richText1.AppendText(String.Format("Loaded Add-in {0} Version {1}",
            addinToken.Name, addinToken.Version));
    }

    calcAddin = _addinList[0];
}
And we are ready to use the addin instance. 
private void btn_Add_Click(object sender, EventArgs e)
{
    if (calcAddin != null)
    {
        //Invoking the AddIn method
        int sum = calcAddin.ComputeSum(
            Convert.ToInt32(textBox1.Text), 
            Convert.ToInt32(textBox2.Text));
        lblResult.Text = sum.ToString();
    }
    else
        MessageBox.Show("AddIn is not loaded"); 
}

Step -3 –Create AddIn View

Create a class library project named AddInView under the Pipeline solution folder.

  • Change the output path to ..\output\AddInViews\

  • Add reference to assemblies System.AddIn and System.AddIn.Contract

The AddInView is an abstract class with methods corresponding to the methods exposed by the Addin. Note that this class should have the attribute [AddInBase]

using System.AddIn.Pipeline;
namespace Demo.AddinView
{
    [AddInBase]
    public abstract class AddInView
    {
        public abstract int ComputeSum(int a, int b);
    }
}

Step – 4 – Create Contract

The contract in the middle of the pipeline is loaded into both Host’s app domain and AddIn’s app domain.

Create a class library and;

  • Change the output path to ..\output\Contracts\
  • Add reference to assemblies System.AddIn and System.AddIn.Contract

 

clip_image007

 

The contract interface should have the [AddInContract] attribute as shown below.

using System.AddIn.Contract;
using System.AddIn.Pipeline;

namespace Demo.Contracts
{
    [AddInContract]
    public interface IContracts:IContract
    {
        int ComputeSum(int a, int b);
    }
}

Step -5 –Create Host Side Adapter

The host-side converts the flow of types between Host View and the contract.

Create a class library project named HostSideAdapters under the Pipeline solution folder

 

  • Change the output path to ..\output\HostSideAdapters\

  • Add reference to assemblies System.AddIn and System.AddIn.Contract

  • Add reference to project Contracts, set Copy Local property to False

  • Add reference to project HostView, set Copy Local property to False

 

clip_image009

Note the [HostAdapter] attribute of the ContractToHostViewAdapter Class below.

using System.AddIn.Pipeline;
using Demo.Contracts;
namespace Demo.HostSideAdapters
{
    [HostAdapter]
    public class ContractToHostViewAdapter : HostView.HostView
    {
        private IContracts _calcContract;
        private ContractHandle _handle;
        public ContractToHostViewAdapter(IContracts contract)
        {
            _calcContract = contract;
            _handle = new ContractHandle(_calcContract);
        }
        public override int ComputeSum(int a, int b)
        {
            return this._calcContract.ComputeSum(a,b);
        }
    }
}

 

Step -6 – Create AddIn Side Adapter

Create a class library project named AddInSideAdapters under the Pipeline solution folder

 

  • Change the output path to ..\output\AddInSideAdapters\

  • Add reference to assemblies System.AddIn and System.AddIn.Contract

  • Add reference to project Contracts, set Copy Local property to False

  • Add reference to project AddInView, set Copy Local property to False

 

clip_image011

Note the [AddInAdapter] attribute of the AddInViewToContractAdapter Class below. The adapter inherits from System.AddIn.Pipeline.ContractBase class and implements  IContracts interface.

using System.AddIn.Pipeline;
using Demo.AddinView;
using Demo.Contracts;
namespace Demo.AddInSideAdapters
{
    [AddInAdapter]
    public class AddInViewToContractAdapter: ContractBase, IContracts
    {
        private AddInView _view;
        public AddInViewToContractAdapter(AddInView view)
        {
            this._view = view;
        }
        public int ComputeSum(int a, int b)
        {
            return this._view.ComputeSum(a,b);
        }
     }
}

Step -7 –Implement AddIn

Create a class library project named CalcAdd under the AddIn solution folder

Change the output path to ..\output\AddIns\CalcAddin\  (If you have multiple Addin, each AddIn would be deployed into separate directories)

  • Add reference to assemblies System.AddIn and System.AddInx.Contract

  • Add reference to project AddInView, set Copy Local property to False

clip_image013

namespace Demo.CalcAddIn
{
    [System.AddIn.AddIn("Demo Add-In", 
     Version = "1.0.0.0",
     Description = "Description of Demo AddIn", 
     Publisher = "XYZ Company")]
    public class CalcAddIn : Demo.AddinView.AddInView
    {
        public override int ComputeSum(int a, int b)
        {
            return a+b;
        }
    }
}

Step -8 – Run the host application

Build the solution and run the host application. You should see the following result.

clip_image015

Alternately you can download the source code from the link below and run it.

Source Code

Pipeline Builder Tool – Making the AddIin development easy

The CLR Add-in team came up with a very useful tool to save the coding effort and complexity associated with add-in development. The tool is available in CodePlex.

I installed the pipeline builder add-in to Visual Studio 2008 and it works great!  Matt Hidinger in his blog describes the steps to use pipeline builder with a sample.

The links that may be of interest to add-in developers are :

Managed AddIn Framework (MAF)

This week, I have started exploring the add-in programming model for plug-in development.  Developers can use it to develop add-ins and activate them in their host application. The model is based on construction of a communication pipeline between the host and the add-in.
Managed Add-in Framework
Managed Add-in Framework
The assemblies for these segments are not required to be in the same application domain. You can load an add-in into its own new application domain, into an existing application domain, or even into the host’s application domain. You can load multiple add-ins into the same application domain, which enables the add-ins to share resources and security contexts.

The add-in model supports, and recommends, an optional boundary between the host and the add-in, which is called the isolation boundary (also known as a remoting boundary). This boundary can be an application domain or process boundary.

The contract segment in the middle of the pipeline is loaded into both the host’s application domain and the add-in’s application domain. The contract defines the virtual methods that the host and the add-in use to exchange types with each other.

To pass through the isolation boundary, types must be either contracts or serializable types. Types that are not contracts or serializable types must be converted to contracts by the adapter segments in the pipeline.

The view segments of the pipeline are abstract base classes or interfaces that provide the host and the add-in with a view of the methods that they share, as defined by the contract. Source : MSDN