I'm trying to duplicate the behavior that I observe in JScript in C#. I am using IDispatch to enumerate members and call them on late-bound objects. I am a complete C++ noob and know just enough about COM to be very dangerous. Here are my question(s):
- Is DISPID_VALUE always zero (0)? (seems yes)
- When calling COM objects, when should I call out to the DISPID_VALUE member? (something like, when the interface itself is indexed or invoked...?)
- Are there any rules/hints for when to call .Item?
- Why, in the example below, does BindingFlags.SetProperty work on .Cells(x, x) (as opposed to BindingFlags.InvokeMethod)? Is it calling _Default(x, x)? Item(x, x)? How does it know to do this? How can I find out which it is calling?
- Is there some good documentation on calling late-bound IDispatch COM objects?
In the example below, an Excel spreadsheet's cell 1,1 has the value set to some text and "bolded".
Consider the following WSH JScript:
var objExcel = new ActiveXObject("Excel.Application");
objExcel.Workbooks.Add();
objExcel.Visible = true;
objExcel.Cells(1,1).Value = "some test value";
objExcel.Cells(1,1).Font.Bold = true;
This C# code creates the same result (yes, sorry it's very verbose):
Type axType = Type.GetTypeFromProgID("Excel.Application");
object objExcel = Activator.CreateInstance(axType);
object workbooks = objExcel.GetType().InvokeMember("Workbooks", System.Reflection.BindingFlags.GetProperty, null, objExcel, null);
objExcel.GetType().InvokeMember("Visible", System.Reflection.BindingFlags.SetProperty, null, objExcel, new object[] { true });
workbooks.GetType().InvokeMember("Add", System.Reflection.BindingFlags.InvokeMethod, null, workbooks, new object[] { true });
object cell = objExcel.GetType().InvokeMember("Cells", System.Reflection.BindingFlags.GetProperty, null, objExcel, new object[] { 1, 1 });
cell.GetType().InvokeMember("Value", System.Reflection.BindingFlags.SetProperty, null, cell, new object[] { "some test value" });
object font = cell.GetType().InvokeMember("Font", System.Reflection.BindingFlags.GetProperty, null, cell, null);
font.GetType().InvokeMember("Bold", System.Reflection.BindingFlags.SetProperty, null, font, new object[] { true });
When I get time one way I plan to try and learn more about this is to have JScript call out to a C# COM class I would create with logging/debugging.