VBA中的VSTO:AddIn.Object有时返回空值(null)

5
给出:
  • 一个VSTO插件
  • 一个override object RequestComAddInAutomationService(),该方法返回一个名为Facade的类的实例。
  • 一个在Excel 2007中的VBA宏,用于访问AddIn.Object以获取Facade并使用它。
  • 许多次这一切都能正常工作。
  • 几次突然之间就不能正常工作了。

更新:原来仅有特定用户遇到了这个问题。她总是有这个问题,其他人从未遇到过(?不要说“从未”)

我得到了以下错误信息:

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

错误发生在试图访问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”,这仍然是有效的。在我的情况下,VBA会在执行一个空引用(即automationObject)上的方法时抛出此类型的错误。
另一方面,如果插件根本不存在,"Application.COMAddIns(...)" 会引发索引超出范围的错误,我之前见过这种情况。
3个回答

3
大部分时间都在工作,但有时会失败,这看起来像是一种竞态条件。Andrew Whitechapel曾写过与RequestComAddInAutomationService1相关的竞态条件:

COMAddIns Race Condition

虽然他说竞态条件不应该是进程内VBA宏的问题,但可能在您的特定情况下出现问题。

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

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

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


谢谢你的提示。我已经阅读了它。不幸的是,它似乎不适用于我的情况:我确实从VBA调用插件。我现在已经将细节添加到我的问题中。如果您能在那段代码中发现竞争条件,我会很高兴。虽然看起来更像是没有...(当然,多次重试的技巧可能仍然有效) - chiccodoro

2
原来Excel禁用了COM插件。有时候这会默默地发生,而Excel并不会有什么抱怨。
因此,由于插件已经在Excel中注册过了,所以以下行的操作是成功的:
Set addin = Application.COMAddIns("My AddIn")

但是因为它被禁用了,所以对象并没有被创建。

Set automationObject = addin.Object

导致结果。


1
这个“答案”说“Excel禁用了COM插件/已知有时会默默发生”,然后解释了这解释了症状。但是,它并没有解释如何防止或解决这个问题。 - Tony Delroy
@TonyD:你说得没错——但这已超出了本问题的范围。问题只是如何发生的。结果是插件被禁用了。询问Excel为什么可能会禁用插件将开启一个全新的可能答案空间... - chiccodoro

1
我遇到过类似的问题,不是总出现,所以不能确定,但似乎解决方法是进入项目 / 应用程序 / 程序集信息...,勾选“使程序集COM可见”,然后在Excel VBA中创建对象:
Set automationObject = CreateObject("PlugInDllName.PlugInClass")

自从那以后就没有问题 - 指望吧。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接