我试图通过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()这样的方法是由intellisense预测的,但我不认为MWS的类型是类型库的一部分。
如果能对此提供任何帮助,我们将不胜感激。
发布于 2020-07-31 04:34:36
正如注释中提到的,您只需使用C# 4特性dynamic即可。它是为COM后期装订而设计的。我是以你的回答为基础的,但我把它整理好了。
MSDN有这在dynamic上说
C#团队在C# 4发行版中专门针对的COM互操作场景是针对Microsoft应用程序(如Word和Excel )进行编程。其目的是使这个任务在C#中像在Visual中一样简单和自然。这也是Visual和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()为止,然后下降到dynamic,这意味着AddToHistory不可用,因为您使用的是旧的/错误的COM引用。第一个例子是如何创建一个独立于版本的CSTStudio.Application。也许可以通过Activator.CreateInstance尝试类似的方法
然后将dynamic与Type.InvokeMethod混合使用。虽然好的,当dynamic可以像上面那样节省时间的时候,这是有点冗长的。
执行部分:
如果我将最后两行代码更改为下面的代码,则它不再工作了(动态MWS = t.InvokeMember("Active3D“、BindingFlags.InvokeMethod、null、CST、null);MWS.AddToHistory(”测试“、”“)。它说它找不到方法。
这是因为您正在使用Type调用这些方法。我怀疑它没有使用延迟绑定,因此为什么使用dynamic。您应该只对使用变量t来表示行Activator.CreateInstance(t),而不使用其他地方。CST和MWS应该是dynamic。
发布于 2020-07-31 01:48:29
通过使用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", ""});这是可行的,但如果有人能解释为什么我的原始代码不起作用,那就太好了。
https://stackoverflow.com/questions/63182924
复制相似问题