The class mshtml.HTMLDocumentClass in Microsoft.mshtml.dll assembly has a method:
public virtual void write(params object[] psarray);
Avoiding the real question for a moment, what code would you use to call write()? Would you use:
String html = "<html><body>Hello, world!</body></html>";
mshtml.HTMLDocumentClass doc;
...
doc.write(html);
or would you use:
String html = "<html><body>Hello, world!</body></html>";
mshtml.HTMLDocumentClass doc;
...
object[] params = new Object[1];
params[0] = html;
doc.write(params);
Because both of those throw an exception. (Type mismatch. 0x80020005)
The HTMLDocumentClass.write method actually comes from IHTMLDocument2 interface, which is documented as:
IHTMLDocument2::write Method
Writes one or more HTML expressions to a document in the specified window.
Syntax
HRESULT write( SAFEARRAY *psarray );
Parameters
psarray
[in] A **BSTR** that specifies the text and HTML tags to write.
So in reality the write method needs a pointer to a SAFEARRAY, even though Microsoft's Microsoft.mshtml interop assembly define the write method as taking a regular array:
public virtual void write(params object[] psarray);
Ignoring the mshtml interop declaration, i have to construct a SAFEARRAY object (verses an object array), fill it with a BSTR string (verses a String), and stuff it into a parameter that must be an object array.
Note: i'm unsure of the meaning of the params keyword. It is used to indicate a variable number of parameters.
Does that mean that it can take multiple array parameters?
object[] array1 = new Object[1];
array1 [0] = alpha;
object[] array2 = new Object[1];
array2 [0] = bravo;
object[] array3 = new Object[1];
array3 [0] = charlie;
object[] array4 = new Object[1];
array4 [0] = delta;
doc.write(array1, array2, array3, array4);
Or is object[] the method in which multiple parameters are passed, and you must literally create an array?
object[] params = new Object[4];
params[0] = alpha;
params[1] = bravo;
params[2] = charlie;
params[3] = delta;
doc.write(params);
Or is the array[] just a decoy, and really you pass:
doc.write(alpha, bravo, charlie, delta);
When i originally used this code, from a native Win32 app, the BSTR was placed inside a SAFEARRAY. In IDispatch based automation, everything is inside an array. In this case the late binding code:
doc.write(html);
was converted by the compiler into a SAFEARRAY, where the zero-th element contains a BSTR string (which is a length prefixed unicode string).
My problem becomes one of trying to construct a SAFEARRAY, converting a String into a BSTR, placing the BSTR into the zero-th element of the SAFEARRAY, and passing a variable that contains a SAFEARRAY to one that only accepts an object array (object[]).
This is the real question: how to create a BSTR SAFEARRAY?
Microsoft.mshtml
C:\Program Files\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll
The declaration for the write method on the IHTMLDocument2
interface created by TLBIMP/VS.NET is incorrect. It should be:
void Write([In, MarshalAs(UnmanagedType.SafeArray)] object[] psarray);
You will have to define this interface in code and then use that.
The params keyword indicates that you can supply multiple parameters in this place, and it will group automatically. For example, if I had a function thus:
public int SumNumbers(params int[] value)
{
//Logic.
}
then I could call it like this:
int myValue = SumNumbers(1,2,3,4,5,6,7,8,9,10);
The array is constructed automagically. So hypothetically, you could call
mshtml.HTMLDocumentClass doc;
...
doc.write('H','I',' ','M','O','M');
And it would work. Not really practical though. I suppose you've tried calling
doc.write(myString.ToCharArray());
? I don't know anything about SAFEARRAYS, but its possible you might not have to know, either, depending on how the compiler helps/hinders here.
It works like a charm this way :
[Guid("332C4425-26CB-11D0-B483-00C04FD90119")]
[ComImport]
[TypeLibType((short)4160)]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
internal interface IHTMLDocument2
{
[DispId(1054)]
void write([MarshalAs(UnmanagedType.BStr)] string psArray); //modified
//void write([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] object[] psarray); //instead of
User contributions licensed under CC BY-SA 3.0