C# VBA中的VSTO:AddIn.Object有时不返回任何内容(null)

C# VBA中的VSTO:AddIn.Object有时不返回任何内容(null),c#,vba,.net-3.5,vsto,excel-2007,C#,Vba,.net 3.5,Vsto,Excel 2007,鉴于: 要加载项的VSTO 一个重写对象RequestComAddInAutomationService(),它返回一个类的实例,在我的场景中该类被称为Facade Excel 2007中的VBA宏,它访问AddIn.Object以获取外观并使用它 很多时候,这种方法都非常有效 有几次,突然之间,这似乎不起作用。 更新:结果发现问题出在某个特定用户身上。她一直拥有它,其他人从未拥有过它(?永远不要说“永远”) 在这“几次”中,我得到了 错误:未设置对象变量或带块变量 在试图访问Facade属

鉴于:

  • 要加载项的VSTO
  • 一个
    重写对象RequestComAddInAutomationService()
    ,它返回一个类的实例,在我的场景中该类被称为
    Facade
  • Excel 2007中的VBA宏,它访问
    AddIn.Object
    以获取外观并使用它
  • 很多时候,这种方法都非常有效
  • 有几次,突然之间,这似乎不起作用。
更新:结果发现问题出在某个特定用户身上。她一直拥有它,其他人从未拥有过它(?永远不要说“永远”)

在这“几次”中,我得到了

错误:未设置对象变量或带块变量

在试图访问
Facade
属性的代码行。简而言之,我可以告诉您,
RequestComAddInAutomationService()
中的代码没有任何容易出错的魔力,访问外接程序的VBA代码也是从web获取的,看起来也不错。对于那些愿意花时间阅读的人来说,更长的版本还没有出现:——)

问题:有人知道为什么会发生这种情况吗?这是Excel问题吗?


承诺的细节:

MyAddIn.cs:

public partial class MyAddIn
{
    public Facade Facade { get; private set; }

    protected override object RequestComAddInAutomationService()
    {
        if (this.Facade == null)
            this.Facade = new Facade(Controller.Instance);

        return this.Facade;
    }
}
Facade.cs:

[ComVisible(true)]
[Guid("1972781C-A71A-48cd-9675-AE47EACE95E8")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IFacade
{
    // some methods
}

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class Facade : IFacade
{
    private Controller Controller { get; set; }

    public Facade(Controller controller)
    {
        this.Controller = controller;
    }
}
Facade
有一些方法,但没有一个字段

Controller.cs:

public class Controller
{
    private static Controller instance = null;
    public static Controller Instance
    {
        get
        {
            if (instance == null) instance = new Controller();
            return instance;
        }
    }

    private Controller() { }
}
Controller
有一些私有字段。因为字段分配是在创建时执行的,所以我对它们进行了检查。它们中的大多数根本没有初始化,或者被设置为
null
,因此构造函数实际上什么也不做

VBA代码:

Dim addin As Office.COMAddIn
Dim automationObject As Object

Set addin = Application.COMAddIns("My AddIn")
Set automationObject = addin.Object

Dim oResult As Object
Set oResult = automationObject.SomeMethodThatReturnsAnObject()
最后一行是发生错误的地方。尽管调用的方法返回了一个对象,但我很确定它不能成为错误的来源:如果返回的引用是
null
,那么该语句将简单地计算为
Set oResult=Nothing
,这仍然有效。每当对
Nothing
的引用执行方法时,VBA就会抛出这种类型的错误,在我的例子中,这是
automationObject


另一方面,如果外接程序根本不存在,
应用程序.COMAddIns(…)
将引发索引越界错误,我以前见过这种情况。

大部分时间都在工作,失败有时看起来像竞争条件。安德鲁·怀特查普(Andrew Whitechapel)曾写过一篇关于
RequestComAddInAutomationService
1:

虽然他说竞争条件不应该是进程内VBA宏的问题,但问题可能发生在您的特定场景中

尝试建议的解决方法并循环,直到您的
Addin.Object
有效(C#code,类似于VBA):


1他的博客上有很多关于您正在做的事情的有用信息,因此不要错过相关文章。

结果是Excel禁用了COM加载项。众所周知,这种情况有时会悄无声息地发生,没有任何抱怨

因此,由于外接程序已在excel中注册,以下行成功:

Set addin = Application.COMAddIns("My AddIn")
但由于该对象已禁用,因此未创建和删除该对象

Set automationObject = addin.Object

结果是
什么都没有

我也遇到过类似的问题,经常但不总是,所以我不能肯定地说,但似乎解决它的问题是项目/应用程序/程序集信息。。。并选中“使部件COM可见”,然后使用以下命令创建对象(在Excel VBA中):


从那以后没有问题-祝你好运。

谢谢你的提示。我读过了。不幸的是,这似乎不适用于我的情况:我确实从VBA调用了外接程序。我现在已经在我的问题中添加了细节。如果你能在代码中找到一个比赛条件,我会很高兴的。虽然看起来好像没有什么。。。(当然,重试几次的技巧可能仍然可以)这个“答案”说“excel禁用了COM加载项/已知有时会无声发生”,然后解释说这解释了症状。但是,它没有解释如何预防或解决这个问题。@TonyD:你说得对,但这超出了这个问题的范围。问题只是它如何发生。原因是外接程序已被禁用。询问Excel为什么可以禁用外接程序,打开了一个全新的可能答案空间。。。
Set automationObject = addin.Object
Set automationObject = CreateObject("PlugInDllName.PlugInClass")