2016-05-10 89 views
1

我之前做過一個原型,使用VSTO並將其方法暴露給其他項目。ComAddin.Object.SomeMethod在一個項目中工作,但不在另一個項目中

現在我試圖實現我的成功使用我目前正在處理的一個項目,但它不起作用。

我得到一個異常消息「System .__ ComObjectenthältkeine DefinitionfürOpen。​​」,這在英文中的意思是儘可能多,因爲ComObject中沒有定義。

我在這裏做錯了什麼?

我檢查了missspellings,引用,如果我忘了執行我的原型,沒有成功的東西。

原來我被指出我在這個答案實現方式:

https://stackoverflow.com/a/35555413/3664953

雖然含有鏈接是要命的,並沒有與VSTO工作的幫助,我沒有看到一個解決方案我這裏的特殊問題。 我也檢查了問題,這個答案中指出:

https://stackoverflow.com/a/3690214/3664953

我嘗試使用的x86編譯的二進制文件,並從4.5.2切換框架回4.5無改變。

€:好吧,就算有行爲的變化,與64位編譯箱(我通常使用「任何CPU」)沒有在ComAddIn的目標的零...

我真的不知道這種行爲在哪裏開始,但也許你會這樣做。

最後,什麼是已經很糟糕的問題,這可能只是因爲我太接近了,沒有看到錯誤,沒有破壞的代碼而被創建。

所以在這裏,我從工作原型開始,還包括新代碼。我削減了一點,所以現在在這兩種解決方案中只有Open方法。

我這樣做,因爲我知道這個問題已經很長了,我不想殺你太多的時間。


的原型是這樣的:

的Controler:

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(); 
} 

的AddIn:

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. 
    } 
} 

外接程序OVERR RequestComAddInAutomationService()的IDE:

private IPropertyReadWriter rw; 

protected override object RequestComAddInAutomationService() 
{ 
    if (rw == null) 
    rw = new PropertyReaderWriter(); 
    return rw; 
} 

程序類:

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」,我只發佈這個來縮短這個非常長的帖子。

接口:

[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); 
} 

在外接程序執行:

[ComVisible(true)] 
[ClassInterface(ClassInterfaceType.None)] 
public class Word_PropertyReadWrite : StandardOleMarshalObject, IPropertyReadWrite_Word 
{ 
    internal static Word.Document Document; 
    internal ThisAddIn home; 

    /// <summary> 
    /// Erzeugt die Klasseninstanz. 
    /// </summary> 
    /// <param name="home">Übergibt das ThisAddIn-Objekt, 
    /// um die Funktionen von Word verwenden zu können.</param> 
    public Word_PropertyReadWrite(ThisAddIn home) 
    { 
    this.home = home; 
    } 

    /// <summary> 
    /// Öffnet die Datei am entsprechenden Pfad. 
    /// </summary> 
    /// <param name="Path">Pfad zur Datei</param> 
    /// <returns>Gibt bei Erfolg true zurück.</returns> 
    public bool Open(string Path) 
    { 
    try 
    { 
     Document = home.Application.Documents.OpenNoRepairDialog(FileName: Path, 
      ConfirmConversions: false, ReadOnly: false, AddToRecentFiles: false, 
      Revert: false, Visible: false, OpenAndRepair: true, NoEncodingDialog: false); 
     return true; 
    } 
    catch 
    { 
     //TODO: Logging 
     //Rethrow der entstandenden Exception. 
     throw; 
    } 
    } 
} 

RequestComAddInAutomationService()的控制裝置:

私人Word_PropertyReadWrite PropertyReadWrite;

protected override object RequestComAddInAutomationService() 
{ 
    //System.Diagnostics.Debugger.Break(); 
    if (PropertyReadWrite == null) 
    PropertyReadWrite = new Word_PropertyReadWrite(this); 
    return PropertyReadWrite; 
} 

最後,這是我的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(); 
    } 
} 
+1

因此,您的(控制檯?)解決方案嘗試調用Word UI中加載的VSTO加載項中的代碼?在第一個實現中,您使用後期綁定(PInvoke)調用Open方法。在第二個,這不起作用,你使用早期綁定。這是一個非常大的差異,你必須有一個原因,你最後使用後期綁定的麻煩? –

+0

嗨,辛迪,睡了一晚之後,我可以把它煮到我的界面。 在我的項目中,我使用了一個從'IPropertyReadWrite_Common'派生的接口calles'IPropertyReadWrite_Word',其中幾乎所有的方法都被定義(包括漏洞Open(字符串路徑))如果我添加_Common作爲我的類的第二個接口,工作......非常奇怪的行爲,我不知道爲什麼會發生這種情況 – ExNought

+1

嗯,你的問題是非常不明確的情況與各種接口。在閱讀這最後的評論,這似乎符合邏輯,我需要被「引用」,如果一個「建立」在另一個......我認爲一個晚上的睡眠是一個非常好的主意:-) –

回答

0

好了,我得到了一個解決方案,這是一個有點奇怪,我加IPropertyReadWrite_Word的parentinterface,叫IPropertyReadWrite_Common,到實現。

現在我的頭看起來像這樣:

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

現在,它就像一個魅力,但我不知道,爲什麼它不應該一直在努力開始......也許有人可以添加一個提示?

這是這樣一個奇怪的現象,我有點懷疑,任何人都將在不久的將來,同樣的問題,因爲我用例是相當......奇:)

在這一點上,我真的想要感謝@辛迪梅斯特,你曾幫助過我這樣一個又一次奇怪的問題,感謝你的耐心!

相關問題