.NET mshtml: Wie ein BSTR SAFEARRAY passieren?
Frage
Die Klasse mshtml.HTMLDocumentClass in Microsoft.mshtml.dll Anordnung hat eine Methode:
public virtual void write(params object[] psarray);
Die eigentliche Frage für einen Moment vermeiden, welcher Code würden Sie verwenden, um rufen write () ? Würden Sie verwenden:
String html = "<html><body>Hello, world!</body></html>";
mshtml.HTMLDocumentClass doc;
...
doc.write(html);
oder verwenden Sie:
String html = "<html><body>Hello, world!</body></html>";
mshtml.HTMLDocumentClass doc;
...
object[] params = new Object[1];
params[0] = html;
doc.write(params);
Weil beide von denen eine Ausnahme werfen. (Typenkonflikt. 0x80020005)
Die HTMLDocumentClass.write Methode tatsächlich kommt von IHTMLDocument2 Schnittstelle , die als dokumentiert ist:
IHTMLDocument2 :: schreiben Methode
Schreibt einen oder mehrere HTML-Ausdrücke ein Dokument im angegebenen Fenster.
Syntax
HRESULT write( SAFEARRAY *psarray );
Parameter
psarray
[in] A **BSTR** that specifies the text and HTML tags to write.
So in Wirklichkeit die Schreibmethode einen Zeiger auf ein SAFEARRAY braucht, auch wenn Microsoft Microsoft.mshtml Interopassembly die definieren schreiben Methode als eine regelmäßige Anordnung unter:
public virtual void write(params object[] psarray);
Ignorieren der mshtml interop Erklärung, ich habe ein konstruieren SAFEARRAY Objekt (Vers eines Objekt-Array), füllt sie mit einem BSTR string (Versen ein String), und so in einen Parameter, der muss sein ein Objekt-Array.
Hinweis: Ich bin nicht sicher über die Bedeutung des params Stichwortes. Es wird verwendet, um eine variable Anzahl von Parametern anzuzeigen.
Heißt das, dass es mehrere Array-Parameter nehmen?
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);
Oder Objekt [] das Verfahren, bei dem mehrere Parameter übergeben, und Sie müssen buchstäblich ein Array erstellen?
object[] params = new Object[4];
params[0] = alpha;
params[1] = bravo;
params[2] = charlie;
params[3] = delta;
doc.write(params);
Oder ist das Array [] nur ein Köder, und wirklich passieren Sie:
doc.write(alpha, bravo, charlie, delta);
Wenn ich ursprünglich diesen Code verwendet wird, von einer nativen Win32-Anwendung, wurde das BSTR in einem SAFEARRAY platziert. In IDispatch basierte Automatisierung, ist alles in einem Array. In diesem Fall wird der späte Bindung Code:
doc.write(html);
durch den Compiler in einen SAFEARRAY umgewandelt wurde, wobei das nullte Element eine BSTR-Zeichenfolge enthält (die eine Länge vorangestellt Unicode-Zeichenfolge).
Mein Problem wird zu einem der versucht, einen SAFEARRAY zu konstruieren, eine Zeichenkette in einem BSTR Umwandeln des BSTR in das nullte Element des SAFEARRAY platzieren, und eine variable vorbei, die eine SAFEARRAY einem enthält, die nur ein Objektarray akzeptiert (Objekt []).
Das ist die eigentliche Frage:? , wie man einen BSTR SAFEARRAY erstellen
Microsoft.mshtml
C: \ Program Files \ Microsoft.NET \ Primary Interop Assemblies \ Microsoft.mshtml.dll
Lösung
Die Erklärung für die Schreibmethode auf der IHTMLDocument2
Schnittstelle von TLBIMP / VS.NET erstellt ist falsch. Es sollte sein:
void Write([In, MarshalAs(UnmanagedType.SafeArray)] object[] psarray);
Sie haben diese Schnittstelle in Code zu definieren und dann verwenden.
Andere Tipps
Das Schlüsselwort params gibt an, dass Sie mehrere Parameter an diesem Ort liefern können, und es wird automatisch Gruppe. Zum Beispiel, wenn ich eine Funktion habe also:
public int SumNumbers(params int[] value)
{
//Logic.
}
dann nenne ich könnte es wie folgt aus:
int myValue = SumNumbers(1,2,3,4,5,6,7,8,9,10);
Das Array wird automatisch aufgebaut. So hypothetisch, könnte man nennen
mshtml.HTMLDocumentClass doc;
...
doc.write('H','I',' ','M','O','M');
Und es funktionieren würde. wenn auch nicht wirklich praktisch. Ich nehme an, Sie haben versucht, ruft
doc.write(myString.ToCharArray());
? Ich weiß nichts über SAFEARRAYS, aber seine möglichen könnten Sie nicht wissen müssen, entweder, je nachdem, wie der Compiler half / behindert hier.
Es funktioniert wie ein Zauber auf diese Weise:
[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