我之前做過一個原型,使用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();
}
}
因此,您的(控制檯?)解決方案嘗試調用Word UI中加載的VSTO加載項中的代碼?在第一個實現中,您使用後期綁定(PInvoke)調用Open方法。在第二個,這不起作用,你使用早期綁定。這是一個非常大的差異,你必須有一個原因,你最後使用後期綁定的麻煩? –
嗨,辛迪,睡了一晚之後,我可以把它煮到我的界面。 在我的項目中,我使用了一個從'IPropertyReadWrite_Common'派生的接口calles'IPropertyReadWrite_Word',其中幾乎所有的方法都被定義(包括漏洞Open(字符串路徑))如果我添加_Common作爲我的類的第二個接口,工作......非常奇怪的行爲,我不知道爲什麼會發生這種情況 – ExNought
嗯,你的問題是非常不明確的情況與各種接口。在閱讀這最後的評論,這似乎符合邏輯,我需要被「引用」,如果一個「建立」在另一個......我認爲一個晚上的睡眠是一個非常好的主意:-) –