VBA中的VSTO:AddIn.Object有时会返回Nothing(null)

时间:2010-11-10 14:52:51

标签: c# vba .net-3.5 vsto excel-2007

假设:

  • VSTO加载项
  • 一个override object RequestComAddInAutomationService(),它返回一个在我的场景中被称为Facade的类的实例。
  • Excel 2007中的VBA宏,它访问AddIn.Object以获取Facade并使用它。
  • 很多时候这种情况非常好。
  • 有几次突然出现,这似乎不起作用。

更新:原来这是一个有问题的特定用户。她总是拥有它,其他人从来没有它(?永远不会说“从不”)

在这“偶尔”中,我得到了

  

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

在尝试访问Facade属性的代码行中。简而言之,我可以告诉你,RequestComAddInAutomationService()中的代码中没有任何容易出错的魔法,并且访问加载项的VBA代码也是从网上获取的,看起来也很好。对于那些花时间阅读它的人来说,还有更长的版本: - )

问题:有没有人知道为什么会发生这种情况?这是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

另一方面,如果加载项根本不存在,Application.COMAddIns(...)会引发索引超出范围错误,我之前已经看到过。< / p>

3 个答案:

答案 0 :(得分:3)

大部分时间工作并且失败有时看起来像是竞争条件。 Andrew Whitechapel撰写了与RequestComAddInAutomationService 1 相关的竞争条件:

  

<强> COMAddIns Race Condition

尽管他说竞争条件不应该是进程内VBA宏的问题,但问题可能发生在您的特定情况中。

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

while (utils == null)
{
    utils = (ComServiceOleMarshal.IAddinUtilities)addin.Object;
    System.Threading.Thread.Sleep(100);
}    
utils.DoSomething();

1 关于你正在做的事情,他的博客上有很多有用的信息,所以千万不要错过相关的文章。

答案 1 :(得分:2)

原来Excel禁用了COM加载项。众所周知,这种情况有时是无声的,没有Excel抱怨任何事情。

因此,由于加载项已在excel中注册,因此以下行成功:

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

但由于它被禁用,因此未创建对象

Set automationObject = addin.Object

导致Nothing

答案 2 :(得分:1)

我遇到了类似的问题,经常但并非总是如此,所以我不能肯定地说,但似乎解决它的事情是项目/应用程序/装配信息......并检查Make assembly COM-可见,然后使用:

创建对象(在Excel VBA中)
Set automationObject = CreateObject("PlugInDllName.PlugInClass")

没有问题 - 手指交叉。