1

我正在尝试通过 C# 访问 COM 对象(CST Studio Suite)。我之前已经通过以下 MATLAB 脚本成功访问并控制了这个对象:

CST = actxserver('CSTStudio.Application'); % Opens CST
CST.FileNew();                             % Creates a new file
MWS = CST.Active3D;                        % Set focus to the new file
MWS.invoke("AddToHistory","Test","");      % Append to history list

这是我试图用来控制 COM 对象的 C# 代码

cst_design_environmentLib.IApplication CST = new cst_design_environmentLib.Application(); // Opens CST
CST.FileNew(); // Creates a new file
dynamic MWS = CST.Active3D(); // Set focus to the new file
MWS.AddToHistory("Test", ""); // Doesn't work, produces an error

一切正常,直到我尝试运行该方法AddToHistory,该方法失败并出现以下错误:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.__ComObject' does not contain a definition for 'AddToHistory'

我知道该方法AddToHistory存在是因为 1)我通过 MATLAB 访问了它,并且 2)它在文档中。那么为什么它不能通过 C# 运行呢?由于MWS对象是动态类型的,我知道在编译时找不到该方法,但在运行时仍然应该找到它,对吧?我已经调试并检查了对象的类型,并且CST两者MWS都是System.__ComObject. 当我检查这些对象的动态视图时,它显示“无法发现有关此对象的更多信息”,因此它似乎没有找到任何方法。

此外,类型CST是类型库的一部分,cst_design_environmentLib因此FileNew()智能感知预测的方法,但我不相信MWS类型库的类型。

对此的任何帮助将不胜感激。

4

2 回答 2

1

我设法通过使用InvokeMember以下方法使其工作:

// Create an instance of CST
Type t = Type.GetTypeFromProgID("CSTStudio.Application");
object CST = Activator.CreateInstance(t);

// Create a new file
t.InvokeMember("FileNew", BindingFlags.InvokeMethod, null, CST, null);

// Set focus to the new file
object MWS = t.InvokeMember("Active3D", BindingFlags.InvokeMethod, null, CST, null);

// Add something to the model history
t.InvokeMember("AddToHistory", BindingFlags.InvokeMethod, null, MWS, new string[] {"Test", ""});

这可行,但如果有人能解释为什么我的原始代码不起作用,那就太好了。

于 2020-07-31T01:48:29.440 回答
1

如评论中所述,您可以只使用 C# 4 功能dynamic。它是为 COM 后期绑定而设计的。我的回答是基于你的,但已经解决了。

MSDN 上有这个要说dynamic

C# 团队在 C# 4 版本中专门针对的 COM 互操作方案是针对 Microsoft Office 应用程序(例如 Word 和 Excel)进行编程。其目的是让 C# 中的这项任务像在 Visual Basic 中一样简单自然。这也是 Visual Basic 和 C# 共同进化战略的一部分,这两种语言都旨在实现功能对等,并相互借鉴最佳和最高效的解决方案。

// Create an instance of CST
Type t = Type.GetTypeFromProgID("CSTStudio.Application");
dynamic CST = Activator.CreateInstance(t);

// Create a new file
CST.FileNew();

// Set focus to the new file
dynamic MWS = CST.Active3D();

// Add something to the model history
MWS.AddToHistory (new string[] {"Test", ""});

这可行,但如果有人能解释为什么我的原始代码不起作用,那就太好了。

正如我在上面的评论中提到的:

我注意到您一直在使用互操作包装器,直到 CST.Active3D() 然后您下拉到动态,这向我暗示 AddToHistory 不可用,因为您使用的是较旧/错误的 COM 引用。第一个示例是如何创建独立于版本的 CSTStudio.Application。也许通过 Activator.CreateInstance 尝试类似的事情

然后,您将 dynamic 与Type.InvokeMethod. 虽然可以,但它有点冗长,什么时候dynamic可以像上面那样节省一天。

操作:

如果我将最后两行代码更改为以下代码,则它不再起作用 dynamic MWS = t.InvokeMember("Active3D", BindingFlags.InvokeMethod, null, CST, null); MWS.AddToHistory("测试", "");。它说它找不到方法。

那是因为您正在使用Type调用方法。我怀疑它不使用后期绑定,因此为什么dynamic. 您应该将变量t用于该行Activator.CreateInstance(t) ,而不要在其他地方使用。 CST并且MWS应该是dynamic

于 2020-07-31T04:34:36.420 回答