.NET mshtml: как сдать BSTR SAFEARRAY?
Класс mshtml.HTMLDocumentClass в сборке Microsoft.mshtml.dll имеет метод:
public virtual void write(params object[] psarray);
Избегая реального вопроса, какой код вы бы использовали для вызова write ()? Вы бы использовали:
String html = "<html><body>Hello, world!</body></html>";
mshtml.HTMLDocumentClass doc;
...
doc.write(html);
или вы бы использовали:
String html = "<html><body>Hello, world!</body></html>";
mshtml.HTMLDocumentClass doc;
...
object[] params = new Object[1];
params[0] = html;
doc.write(params);
Потому что оба из них бросают исключение. (Несоответствие типов. 0x80020005)
Метод HTMLDocumentClass.write фактически происходит из интерфейса IHTMLDocument2, который задокументирован как:
IHTMLDocument2:: write Метод
Записывает одно или несколько HTML-выражений в документ в указанном окне.
Синтаксис
HRESULT write( SAFEARRAY *psarray );
параметры
psarray
[in] A **BSTR** that specifies the text and HTML tags to write.
Так что в действительности для метода записи требуется указатель на SAFEARRAY, хотя сборка взаимодействия Microsoft.mshtml от Microsoft определяет метод записи в виде обычного массива:
public virtual void write(params object[] psarray);
Игнорируя объявление взаимодействия mshtml, я должен создать объект SAFEARRAY (стихи массив объектов), заполнить его строкой BSTR (стихи String) и вставить в параметр, который должен быть массивом объектов.
Примечание: я не уверен в значении ключевого слова params. Используется для указания переменного количества параметров.
Означает ли это, что он может принимать несколько параметров массива?
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);
Или объект [] - это метод, в котором передается несколько параметров, и вы должны буквально создать массив?
object[] params = new Object[4];
params[0] = alpha;
params[1] = bravo;
params[2] = charlie;
params[3] = delta;
doc.write(params);
Или массив [] просто приманка, и вы действительно передаете:
doc.write(alpha, bravo, charlie, delta);
Когда я первоначально использовал этот код из собственного приложения Win32, BSTR был помещен в SAFEARRAY. В автоматизации на основе IDispatch все находится внутри массива. В этом случае код позднего связывания:
doc.write(html);
был преобразован компилятором в SAFEARRAY, где нулевой элемент содержит строку BSTR (которая является строкой Unicode с префиксом длины).
Моя проблема заключается в попытке создать SAFEARRAY, преобразовать строку в BSTR, поместить BSTR в нулевой элемент SAFEARRAY и передать переменную, содержащую SAFEARRAY, в переменную, которая принимает только массив объектов (object[]).
Это реальный вопрос: как создать BSTR SAFEARRAY?
Microsoft.mshtml
C: \ Program Files \ Microsoft.NET \ Первичные сборки взаимодействия \Microsoft.mshtml.dll
3 ответа
Объявление для метода записи на IHTMLDocument2
интерфейс, созданный TLBIMP/VS.NET, неверен. Так должно быть:
void Write([In, MarshalAs(UnmanagedType.SafeArray)] object[] psarray);
Вам нужно будет определить этот интерфейс в коде, а затем использовать его.
Это работает как очарование таким образом:
[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
Ключевое слово params указывает, что вы можете указать несколько параметров в этом месте, и оно будет сгруппировано автоматически. Например, если бы у меня была функция таким образом:
public int SumNumbers(params int[] value)
{
//Logic.
}
тогда я мог бы назвать это так:
int myValue = SumNumbers(1,2,3,4,5,6,7,8,9,10);
Массив строится автоматически. Так что гипотетически, вы могли бы позвонить
mshtml.HTMLDocumentClass doc;
...
doc.write('H','I',' ','M','O','M');
И это будет работать. Не очень практично, хотя. Я полагаю, вы пытались позвонить
doc.write(myString.ToCharArray());
? Я ничего не знаю о SAFEARRAYS, но, возможно, вам, возможно, и не придется знать, в зависимости от того, как компилятор помогает / мешает здесь.