C# ComAddin.Object.SomeMethod在一个项目中有效,但在另一个项目中无效

C# ComAddin.Object.SomeMethod在一个项目中有效,但在另一个项目中无效,c#,com,vsto,office-interop,C#,Com,Vsto,Office Interop,不久前我做了一个原型,使用VSTO并将其方法公开给另一个项目 现在,我尝试将我当时成功的应用到我目前正在进行的项目中,但没有成功 我收到一条异常消息“System.u ComObject enthält keine Definition für Open.”,它在英语中的意思与该ComObject中没有定义一样多 我做错了什么 我检查了拼写错误、引用,如果我忘记实现我对原型所做的事情,但没有成功 最初,我在回答中提到了我的实施方式: 虽然包含的链接非常有用,并且确实有助于在VSTO工作,但我在

不久前我做了一个原型,使用VSTO并将其方法公开给另一个项目

现在,我尝试将我当时成功的应用到我目前正在进行的项目中,但没有成功

我收到一条异常消息“System.u ComObject enthält keine Definition für Open.”,它在英语中的意思与该ComObject中没有定义一样多

我做错了什么

我检查了拼写错误、引用,如果我忘记实现我对原型所做的事情,但没有成功

最初,我在回答中提到了我的实施方式:

虽然包含的链接非常有用,并且确实有助于在VSTO工作,但我在这里看不到解决我的特定问题的方法。 我还检查了问题,这个答案指出:

我尝试使用x86编译的二进制文件,并将框架从4.5.2切换回4.5,没有任何更改

欧元:嗯,好的,行为有变化,对于x64编译的容器(我通常使用“任何CPU”),ComAddIn的对象中有一个空值

我真的不知道这种行为的起源,但也许你知道

最后,什么是一个已经很糟糕的问题,这可能只是因为我太近了,没有看到错误,没有损坏的代码

现在,我从工作原型开始,并包括新代码。我切了一点,所以现在两种解决方案中只有开放方法

我这样做了,因为我知道这个问题已经非常长了,我不想浪费你太多的时间


原型如下所示:

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class Word_PropertyReadWrite : StandardOleMarshalObject, IPropertyReadWrite_Common,
    IPropertyReadWrite_Word
控制器:

static void Main(string[] args)
{
  Microsoft.Office.Interop.Word.Application wd = 
    new Microsoft.Office.Interop.Word.Application();
  wd.Visible = false;
  object addinName = "Worker_AddIn";
  foreach (Microsoft.Office.Core.COMAddIn comaddin in wd.COMAddIns)
  {
    if (comaddin.ProgId.Equals(addinName.ToString(), 
           StringComparison.InvariantCultureIgnoreCase))
    {
      object addinObj = comaddin.Object;
      object[] invokeArgs = { "Dummy" };

      object retVal = 
                    addinObj.
                        GetType().
                        InvokeMember("Open", System.Reflection.BindingFlags.InvokeMethod, 
                        null, addinObj, invokeArgs);

      //dynamics ...
      var t1 = comaddin.Object.Open("Dummy");
      var t2 = comaddin.Object.GetCustomProperties();
      var t3 = comaddin.Object.SetCustomProperty("Test",
                 PropertyTypes.msoPropertyTypeBoolean, 42);
    }
  }
  //Properly close Word
  wd.Quit();
}
艾丁:

PropertyReaderWriter及其接口:

public enum WordBuiltinProperties
{
  //some enums
}

public enum PropertyTypes
{
  //more enums
}

[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IPropertyReadWriter
{
  bool Open(string Path);
  //There are more methods, but this one is already causing problems, 
  //also the others don't work either, so I kept the simplest one ;)
}

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class PropertyReaderWriter : StandardOleMarshalObject, IPropertyReadWriter
{
  public bool Open(string Path)
  {
    return false;
    //This was a test, if I could actually use those methods outside of VSTO, 
    //so I didn't implement logic, since I know the stuff I need works in VSTO.
  }
}
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IPropertyReadWrite_Common
{
  /// <summary>
  /// Soll die Datei am entsprechenden Pfad öffnen.
  /// </summary>
  /// <param name="Path">Pfad zur Datei</param>
  /// <returns>Gibt Erfolg/true oder Misserfolg/false zurück.</returns>
  bool Open(string Path);
}
RequestComAddInAutomationService()的加载项重写:

程序类:

Microsoft.Office.Interop.Word.Application wd = 
  new Microsoft.Office.Interop.Word.Application();
wd.Visible = false;
object addinName = "Worker_AddIn";
foreach (Microsoft.Office.Core.COMAddIn comaddin in wd.COMAddIns)
{
  if (comaddin.ProgId.Equals(addinName.ToString(), 
       StringComparison.InvariantCultureIgnoreCase))
  {
    object addinObj = comaddin.Object;
    object[] invokeArgs = { "Dummy" };
    object retVal = addinObj.
                     GetType().
                     InvokeMember("Open", System.Reflection.BindingFlags.InvokeMethod, 
                                  null, addinObj, invokeArgs);
    //dynamics ...
    var t1 = comaddin.Object.Open("Dummy");
    var t2 = comaddin.Object.GetCustomProperties();
    var t3 = comaddin.Object.SetCustomProperty("Test", PropertyTypes.msoPropertyTypeBoolean,
                                               42);
  }
}
//Properly close Word
wd.Quit();

我的项目中的实现如下所示

对于这个接口,我有一个派生接口,称为IPropertyReadWrite_Word,在其中我添加了更多的方法,而不是重写。 另外,我在最后的实现中使用了IPropertyReadWrite_Word,但由于正是这个接口定义了“Open”,所以我只发布这个,以缩短非常长的帖子

接口:

public enum WordBuiltinProperties
{
  //some enums
}

public enum PropertyTypes
{
  //more enums
}

[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IPropertyReadWriter
{
  bool Open(string Path);
  //There are more methods, but this one is already causing problems, 
  //also the others don't work either, so I kept the simplest one ;)
}

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class PropertyReaderWriter : StandardOleMarshalObject, IPropertyReadWriter
{
  public bool Open(string Path)
  {
    return false;
    //This was a test, if I could actually use those methods outside of VSTO, 
    //so I didn't implement logic, since I know the stuff I need works in VSTO.
  }
}
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IPropertyReadWrite_Common
{
  /// <summary>
  /// Soll die Datei am entsprechenden Pfad öffnen.
  /// </summary>
  /// <param name="Path">Pfad zur Datei</param>
  /// <returns>Gibt Erfolg/true oder Misserfolg/false zurück.</returns>
  bool Open(string Path);
}
最后,这是到目前为止我的testclass:

static void Main(string[] args)
{
  Microsoft.Office.Interop.Word.Application wd = 
    new Microsoft.Office.Interop.Word.Application();
  wd.Visible = false;
  object addinName = "Dokumentenvorbereitung_Word_AddIn";
  try
  {
    Microsoft.Office.Core.COMAddIn addin = 
      wd.COMAddIns.Item(ref addinName);
    foreach (Microsoft.Office.Core.COMAddIn comaddin in wd.COMAddIns)
    {
      if (comaddin.ProgId.Equals(addinName.ToString(),
          StringComparison.InvariantCultureIgnoreCase))
      {
        var test = (comaddin).Object.Open(@"Path to some valid .docx");
      }
    }
  }
  catch(Exception e)
  {
    //...
  }
  finally
  {
    wd.Quit();
  }
}

我找到了一个解决方案,有点奇怪,我在实现中添加了IPropertyReadWrite_Word的parentinterface,称为IPropertyReadWrite_Common

现在,我的标题如下所示:

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class Word_PropertyReadWrite : StandardOleMarshalObject, IPropertyReadWrite_Common,
    IPropertyReadWrite_Word
现在它就像一个符咒,虽然我不确定,为什么它一开始就不起作用。。。也许有人能给你一个提示

这是一个如此奇怪的行为,我有点怀疑,在不久的将来,任何人都会有同样的问题,因为我的用例非常。。。奇数:)


在这一点上,我真的很想感谢@Cindy Meister,你已经两次又一次地帮助我提出了这样一个奇怪的问题,谢谢你的耐心

那么,您的(控制台?)解决方案试图调用加载在Word UI中的VSTO加载项中的代码?在第一个实现中,使用后期绑定(PInvoke)调用Open方法。在第二种情况下,这不起作用,使用早期绑定。这是一个相当大的区别,而且一定有一个原因让你费尽心机去使用后期绑定,最初?嗨,辛迪,经过一夜的睡眠,我可以把它归结为我的界面。在我的项目中,我使用了一个名为“IPropertyReadWrite_Word”的接口,该接口源自“IPropertyReadWrite_Common”,其中定义了几乎所有的方法(包括错误的Open(字符串路径)。如果我添加_Common作为我的类的第二个接口,它似乎会起作用…非常奇怪的行为,我不知道为什么会发生这种情况。嗯,你的问题对于各种接口的情况肯定不是很清楚。在阅读最后一条评论时,在我看来,如果一个接口“构建”,那么这两个接口都需要“引用”另一方面……我认为晚上睡一觉是一个非常好的主意:-)