.NET mshtml: ¿Cómo pasar un BSTR SAFEARRAY?
com interop (3)
La palabra clave params indica que puede suministrar múltiples parámetros en este lugar, y se agrupará automáticamente. Por ejemplo, si tuviera una función así:
public int SumNumbers(params int[] value)
{
//Logic.
}
entonces podría llamarlo así:
int myValue = SumNumbers(1,2,3,4,5,6,7,8,9,10);
La matriz está construida automágicamente. Entonces, hipotéticamente, podrías llamar
mshtml.HTMLDocumentClass doc;
...
doc.write(''H'',''I'','' '',''M'',''O'',''M'');
Y funcionaría. Aunque no es realmente práctico. Supongo que has intentado llamar
doc.write(myString.ToCharArray());
? No sé nada sobre SAFEARRAYS, pero es posible que no tengas que saberlo, dependiendo de cómo el compilador ayude / entorpezca aquí.
La clase mshtml.HTMLDocumentClass en el ensamblado Microsoft.mshtml.dll tiene un método:
public virtual void write(params object[] psarray);
Evitando la pregunta real por un momento, ¿qué código utilizarías para llamar a write () ? ¿Usarías:
String html = "<html><body>Hello, world!</body></html>";
mshtml.HTMLDocumentClass doc;
...
doc.write(html);
o usarías:
String html = "<html><body>Hello, world!</body></html>";
mshtml.HTMLDocumentClass doc;
...
object[] params = new Object[1];
params[0] = html;
doc.write(params);
Porque ambos arrojan una excepción. (No coincide el tipo. 0x80020005)
El método HTMLDocumentClass.write en realidad proviene de la interfaz IHTMLDocument2 , que está documentado como:
IHTMLDocument2 :: método de escritura
Escribe una o más expresiones HTML en un documento en la ventana especificada.
Sintaxis
HRESULT write( SAFEARRAY *psarray );
Parámetros
psarray
[in] A **BSTR** that specifies the text and HTML tags to write.
Entonces, en realidad, el método de escritura necesita un puntero a un SAFEARRAY, aunque el ensamblado de interoperabilidad Microsoft.mshtml de Microsoft define el método de escritura como una matriz regular:
public virtual void write(params object[] psarray);
Ignorando la declaración de interferencia mshtml, tengo que construir un objeto SAFEARRAY (frente a una matriz de objetos), llenarlo con una cadena BSTR (versos de una cadena) y rellenarlo en un parámetro que debe ser una matriz de objetos.
Nota: no estoy seguro del significado de la palabra clave params . Se usa para indicar una cantidad variable de parámetros.
¿Eso significa que puede tomar múltiples parámetros de matriz?
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);
¿O es objeto [] el método en el que se pasan múltiples parámetros, y debe crear literalmente una matriz?
object[] params = new Object[4];
params[0] = alpha;
params[1] = bravo;
params[2] = charlie;
params[3] = delta;
doc.write(params);
¿O es la matriz [] solo un señuelo, y realmente pasas:
doc.write(alpha, bravo, charlie, delta);
Cuando utilicé originalmente este código, desde una aplicación Win32 nativa, el BSTR se colocó dentro de un SAFEARRAY. En la automatización basada en IDispatch, todo está dentro de una matriz. En este caso, el código de enlace tardío:
doc.write(html);
fue convertido por el compilador en un SAFEARRAY, donde el elemento cero-th contiene una cadena BSTR (que es una cadena Unicode con prefijo de longitud).
Mi problema es tratar de construir un SAFEARRAY, convertir un String en un BSTR, colocar el BSTR en el elemento cero del SAFEARRAY y pasar una variable que contiene un SAFEARRAY a uno que solo acepte un conjunto de objetos (objeto [ ]).
Esta es la verdadera pregunta: ¿cómo crear un BSTR SAFEARRAY?
Microsoft.mshtml
C: / Archivos de programa / Microsoft.NET / Primary Interop Assemblies / Microsoft.mshtml.dll
Funciona como un encanto de esta manera:
[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
La declaración para el método de escritura en la interfaz IHTMLDocument2
creada por TLBIMP / VS.NET es incorrecta. Debería ser:
void Write([In, MarshalAs(UnmanagedType.SafeArray)] object[] psarray);
Deberá definir esta interfaz en el código y luego usar eso.