I am trying to access a COM object (CST Studio Suite) through C#. I have previously successfully accessed and controlled this object through the following MATLAB script:
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
This is the C# code I am trying to use to control the COM object
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
It all works up until I try to run the method AddToHistory
, which fails and gives the following error:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'System.__ComObject' does not contain a definition for 'AddToHistory'
I know that the method AddToHistory
exists because 1) I have accessed it through MATLAB and 2) it is here in the documentation. So why won't it run through C#? Since the MWS
object is dynamically typed, I get that the method won't be found at compile time, but it should still be found at runtime right? I have debugged and inspected the types of the objects and both CST
and MWS
are System.__ComObject
. When I inspect the dynamic view of these objects, it says "No further information on this object could be discovered" so it doesn't seem to be finding any methods.
Also, the type of CST
is part of the type library cst_design_environmentLib
so the methods such as FileNew()
are predicted by intellisense, but I don't believe that the type of MWS
is part of the type library.
Any help with this would be greatly appreciated.
As mentioned in the comments you can just use the C# 4 feature dynamic
. It was made for COM late-binding in mind. I've based my answer on yours but tided it up.
MSDN has this to say on 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.
As I mentioned in the comments above:
I notice you are using the interop wrapper up to the point of CST.Active3D() then you drop down to dynamic which suggests to me AddToHistory isn't available because you are using an older/wrong COM reference. The first example is how one would go about creating a version independent CSTStudio.Application. Maybe try a similar thing via Activator.CreateInstance
You then mixed dynamic with Type.InvokeMethod
. Whilst OK it's kinda verbose when dynamic
can save the day as per above.
OP:
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.
That's because you are using Type
to call the methods. I suspect it doesn't use late-binding hence why dynamic
. You should only be using the variable t
for the line Activator.CreateInstance(t)
and no where else. CST
and MWS
should be dynamic
.