【问题标题】:VSTO in VBA: AddIn.Object returns Nothing (null) sometimesVBA 中的 VSTO:AddIn.Object 有时返回 Nothing (null)
【发布时间】:2011-05-07 22:32:45
【问题描述】:

给定:

  • 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(...) 会引发 index out of bounds 错误,我以前见过。

【问题讨论】:

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


    【解决方案1】:

    大部分时间都在工作而失败有时看起来像是一种竞争条件。 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 调用加载项。我现在已将详细信息添加到我的问题中。如果您能在该代码中发现竞争条件,我会很高兴。虽然看起来更像没有......(当然,重试几次技巧仍然可以做到)
    【解决方案2】:

    原来 Excel 禁用了 COM 加载项。众所周知,这有时会悄无声息地发生,而 Excel 不会抱怨任何事情。

    所以,既然插件是用excel注册的,下面一行就成功了:

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

    但是由于它被禁用了,所以对象并没有被创建并且

    Set automationObject = addin.Object
    

    导致Nothing

    【讨论】:

    • 这个“答案”说“excel禁用了COM加载项/已知有时会默默发生”,然后解释说这解释了症状。但是,它没有说明如何预防或解决此问题。
    • @TonyD:你说得对 - 但这超出了这个问题的范围。问题只是它是如何发生的。原因原来是加载项被禁用。询问为什么 Excel 可以想象禁用加载项会打开一个全新的可能答案空间......
    【解决方案3】:

    我经常遇到类似的问题,但并非总是如此,所以我不能肯定地说,但似乎可以解决它的事情是项目/应用程序/程序集信息...并检查 Make assembly COM-可见,然后创建对象(在 Excel VBA 中):

    Set automationObject = CreateObject("PlugInDllName.PlugInClass")
    

    没有问题,因为 - 手指交叉。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-14
      • 1970-01-01
      • 2014-01-31
      • 1970-01-01
      相关资源
      最近更新 更多