C# 动态 COM 对象找不到方法
C# Dynamic COM Object can't find Method
我正在尝试通过 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) 它在 documentation 中。那么为什么它不能通过 C# 运行 呢?由于 MWS
对象是动态类型的,我知道在编译时不会找到该方法,但它仍然应该在 运行 时找到,对吗?我已经调试并检查了对象的类型,CST
和MWS
都是System.__ComObject
。当我检查这些对象的动态视图时,它说“无法发现有关此对象的更多信息”,所以它似乎没有找到任何方法。
此外,CST
的类型是类型库cst_design_environmentLib
的一部分,所以FileNew()
等方法是由intellisense预测的,但我不相信类型MWS
是类型库的一部分。
如有任何帮助,我们将不胜感激。
我按照以下方法使用 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", ""});
这是可行的,但如果有人能解释为什么我的原始代码不起作用,那就太好了。
如评论中所述,您可以只使用 C# 4 功能 dynamic
。它是为 COM 后期绑定而设计的。我的回答基于您的回答,但经过整理。
MSDN 在 dynamic
上有 this 说
The COM interop scenario that the C# team specifically targeted in the C# 4 release was programming against Microsoft Office applications, such as Word and Excel. The intent was to make this task as easy and natural in C# as it always was in Visual Basic. This is also a part of the Visual Basic and C# co-evolution strategy, where both languages aim at feature parity and borrow the best and most productive solutions from one another.
// 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", ""});
This works but it would be great if someone could explain why my original code didn't work.
正如我在上面的评论中提到的:
我注意到您一直在使用互操作包装器直到 CST.Active3D() 然后您下降到动态,这对我来说表明 AddToHistory 不可用,因为您使用的是 older/wrong COM 参考。第一个例子是如何创建一个独立的版本 CSTStudio.Application。也许通过 Activator.CreateInstance
尝试类似的事情
然后您将动态与 Type.InvokeMethod
混合。虽然没关系,但当 dynamic
可以按上述方式挽救一天时,它有点冗长。
原帖:
If I change the last two lines of code to the following it doesn't work anymore dynamic MWS = t.InvokeMember("Active3D", BindingFlags.InvokeMethod, null, CST, null); MWS.AddToHistory("Test", "");. It says it can't find the method.
那是因为您正在使用 Type
调用方法。我怀疑它不使用后期绑定,因此为什么 dynamic
。您应该 仅 将变量 t
用于行 Activator.CreateInstance(t)
而不是其他地方。 CST
和 MWS
应该是 dynamic
.
我正在尝试通过 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) 它在 documentation 中。那么为什么它不能通过 C# 运行 呢?由于 MWS
对象是动态类型的,我知道在编译时不会找到该方法,但它仍然应该在 运行 时找到,对吗?我已经调试并检查了对象的类型,CST
和MWS
都是System.__ComObject
。当我检查这些对象的动态视图时,它说“无法发现有关此对象的更多信息”,所以它似乎没有找到任何方法。
此外,CST
的类型是类型库cst_design_environmentLib
的一部分,所以FileNew()
等方法是由intellisense预测的,但我不相信类型MWS
是类型库的一部分。
如有任何帮助,我们将不胜感激。
我按照以下方法使用 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", ""});
这是可行的,但如果有人能解释为什么我的原始代码不起作用,那就太好了。
如评论中所述,您可以只使用 C# 4 功能 dynamic
。它是为 COM 后期绑定而设计的。我的回答基于您的回答,但经过整理。
MSDN 在 dynamic
The COM interop scenario that the C# team specifically targeted in the C# 4 release was programming against Microsoft Office applications, such as Word and Excel. The intent was to make this task as easy and natural in C# as it always was in Visual Basic. This is also a part of the Visual Basic and C# co-evolution strategy, where both languages aim at feature parity and borrow the best and most productive solutions from one another.
// 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", ""});
This works but it would be great if someone could explain why my original code didn't work.
正如我在上面的评论中提到的:
我注意到您一直在使用互操作包装器直到 CST.Active3D() 然后您下降到动态,这对我来说表明 AddToHistory 不可用,因为您使用的是 older/wrong COM 参考。第一个例子是如何创建一个独立的版本 CSTStudio.Application。也许通过 Activator.CreateInstance
尝试类似的事情然后您将动态与 Type.InvokeMethod
混合。虽然没关系,但当 dynamic
可以按上述方式挽救一天时,它有点冗长。
原帖:
If I change the last two lines of code to the following it doesn't work anymore dynamic MWS = t.InvokeMember("Active3D", BindingFlags.InvokeMethod, null, CST, null); MWS.AddToHistory("Test", "");. It says it can't find the method.
那是因为您正在使用 Type
调用方法。我怀疑它不使用后期绑定,因此为什么 dynamic
。您应该 仅 将变量 t
用于行 Activator.CreateInstance(t)
而不是其他地方。 CST
和 MWS
应该是 dynamic
.