VSTO加载项,COMAddIns和RequestComAddInAutomationService

时间:2012-06-04 01:04:35

标签: c# com vsto add-in msdn

请参阅第一个编辑(底部的屏幕截图):

我已经按照本文的说法让Winform应用程序触发VSTO加载项方法: http://blogs.msdn.com/b/andreww/archive/2007/01/15/vsto-add-ins-comaddins-and-requestcomaddinautomationservice.aspx

在上面文章的最后,作者提到了一个问题并试图在这里改进它: http://blogs.msdn.com/b/andreww/archive/2008/08/11/why-your-comaddin-object-should-derive-from-standardolemarshalobject.aspx

我现在已经多次通过代码了,派生StandardOleMarshalObject以改善异常的方法不起作用

System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' to interface type ... This operation failed because the QueryInterface call on the COM component for the interface with IID

这是一个复制品 - 两个项目的目标都是.Net 3.5:

a)创建一个新办公室> 2007年或2010年> Excel加载项:

namespace ExcelAddIn1
{
    public partial class ThisAddIn
    {
        private AddinUtilities addinUtilities;
        protected override object RequestComAddInAutomationService()
        {
            if (addinUtilities == null)
            {
                addinUtilities = new AddinUtilities();
            }
            return addinUtilities;
        }
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
        }
        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        }
}
}

b)将一个类添加到Excel加载项:

namespace ExcelAddIn1
{
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAddinUtilities
{
    void DisplayMessage();
}

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class AddinUtilities :
    StandardOleMarshalObject,
    IAddinUtilities
{
    void IAddinUtilities.DisplayMessage()
    {
        MessageBox.Show("Hello World");
    }
}
}

c)设置项目属性>构建> seklect注册COM Interop。编译加载项。

d)新的Winform应用程序,引用ExcelAddIn1,Microsoft.Office.Interop.Excel和Office并在Form1中包含此代码:

public partial class Form1 : Form
{
private Microsoft.Office.Interop.Excel.Application excel;
private IAddinUtilities utils;
public Form1()
{
    InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
    excel = new Microsoft.Office.Interop.Excel.Application();
    excel.Visible = true;
    excel.Workbooks.Add(Microsoft.Office.Interop.Excel.XlSheetType.xlWorksheet);
    object addinName = "ExcelAddin1";
    COMAddIn addin = excel.COMAddIns.Item(ref addinName);
    utils = (IAddinUtilities)addin.Object;
    utils.DisplayMessage();
}
}

e)运行Winform应用程序,无论AddinUtilities是否派生自StandardOleMarshalObject,行utils = (IAddinUtilities)addin.Object;都会失败。

我在这里不知所措,因为MSDN博客特别说:“要解决所有这些问题,你可以简单地从StandardOleMarshalObject派生出AddinUtilities类,然后重建:”

第一次编辑:我在另一台PC-B上尝试了该代码,但它的工作原理并非来自StandardOleMarshalObject

enter image description here

当我在PC-B上尝试使用StandardOleMarshalObject时,我遇到了与PC-A相同的问题。 PC-A不适用于任何一种方式,我能想到的唯一区别是管理员权限。

enter image description here

管理员权限和pre-Win7(旧的msdn文章)是我能想到为什么它不起作用的唯一原因。

1 个答案:

答案 0 :(得分:2)

设置Register For Com interop 后,我发现您确实需要以管理员身份运行。

如果没有管理员尝试编译,我会收到如下错误:

  

无法注册程序集“C:\ TFS \ Project \ Src \ ProjectAddin \ bin \ Debug   \ ProjectAddin.dll“ - 访问被拒绝。请确保您正在运行   作为管理员的应用程序访问注册表项   'HKEY_CLASSES_ROOT \ CLSID {3A6192EA-3C9C-39EB-99A3-3DBFF8CA118F}'是   拒绝。

上面的注册表项不存在所以我创建了它,然后尝试编译我得到了:

  

无法注册类型库   “C:\ TFS \ Project \ Src \ ProjectAddin \ bin \ Debug \ ProjectAddin.tlb”。错误   访问OLE注册表。 (来自HRESULT的例外:0x8002801C   (TYPE_E_REGISTRYACCESS))

解决方案

关闭注册COM互操作并且错误消失 - 但这会导致它无法正常工作!

Shift +右键单击Visual Studio并以管理员身份打开,打开项目。勾选注册Com interop并成功编译,当从StandardOleMarshalObject派生时,它现在可以在PC-A上运行 - but it doesn't work without StandardOleMarshalObject - which is the opposite results I got on PC-B