请参阅第一个编辑(底部的屏幕截图):
我已经按照本文的说法让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
,
当我在PC-B上尝试使用StandardOleMarshalObject
时,我遇到了与PC-A相同的问题。 PC-A不适用于任何一种方式,我能想到的唯一区别是管理员权限。
管理员权限和pre-Win7(旧的msdn文章)是我能想到为什么它不起作用的唯一原因。
答案 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
。