Frage

In meiner letzten Entwicklungsumgebung konnte ich leicht mit COM zu interagieren, das Aufrufen von Methoden auf COM-Objekten. Hier ist der ursprüngliche Code, übersetzt in C # Artcode (die Originalsprache zu maskieren):

public static void SpawnIEWithSource(String szSourceHTML)
{
    OleVariant ie; //IWebBrowser2
    OleVariant ie = new InternetExplorer();
    ie.Navigate2("about:blank");

    OleVariant webDocument = ie.Document;
    webDocument.Write(szSourceHTML);
    webDocument.close;

    ie.Visible = True;
}

Nun beginnt den langwierigen, schmerzhaft, Prozess der versucht, aus verwaltetem Code mit COM Interop.

PInvoke.net enthält bereits die IWebBrower2 Übersetzung , die relavent porition von das ist:

[ComImport, 
   DefaultMember("Name"), 
   Guid("D30C1661-CDAF-11D0-8A3E-00C04FC9E26E"), 
   InterfaceType(ComInterfaceType.InterfaceIsIDispatch), 
   SuppressUnmanagedCodeSecurity]
public interface IWebBrowser2
{
    [DispId(500)]
    void Navigate2([In] ref object URL, [In] ref object Flags, [In] ref object TargetFrameName, [In] ref object PostData, [In] ref object Headers);

    object Document { [return: MarshalAs(UnmanagedType.IDispatch)] [DispId(0xcb)] get; }
}

Ich habe die COM-Klasse erstellt:

[ComImport]
[Guid("0002DF01-0000-0000-C000-000000000046")]
public class InternetExplorer
{
}

So, jetzt ist es Zeit für meine eigentliche C # Transaktion:

public static void SpawnIEWithSource(String szHtml)
{
    PInvoke.ShellDocView.IWebBrowser2 ie;
    ie = (PInvoke.ShellDocView.IWebBrowser2)new PInvoke.ShellDocView.InternetExplorer();

    //Navigate to about:blank to initialize the browser
    object o = System.Reflection.Missing.Value;
    String url = @"about:blank";
    ie.Navigate2(ref url, ref o, ref o, ref o, ref o);

    //stuff contents into the document
    object webDocument = ie.Document;
    //webDocument.Write(szHtml);
    //webDocument.Close();

    ie.Visible = true;
}

Die sorgfältigen Leser bemerken, dass IWebBrowser2.Document ist ein spät gebundene IDispatch. Wir verwenden Visual Studio 2005, .NET 2.0 auf unsere und unserer Kunden, Maschinen.

Was ist also die .NET 2.0-Methode Methoden auf einem Objekt aufrufen, die, auf einer bestimmten Ebene, unterstützt nur spät gebundene IDispatch?

Eine schnelle Suche von Stack-Überlauf für die Verwendung von IDispatch von C # taucht diesen Beitrag sagen, was ich will in .NET ist nicht möglich.

So ist es möglich, COM zu verwenden, um von C # .NET 2.0?


Die Frage ist, dass es ein akzeptiertes Entwurfsmuster, die ich in C # /. NET verwenden möge. Es geht aus Internet Explorer-Prozess startet, und es HTML-Inhalte geben, die ganze Zeit temporäre Dateien nicht verwendet wird.

Ein abgelehnter Design-Idee ist auf einem WinForm Internet Explorer Hosting.

Eine akzeptable Alternative startet das System Web-Browser registriert, es HTML geben angezeigt werden, ohne eine temporäre Datei verwendet wird.

Der Stein des Anstoßes ist weiterhin COM-Objekte in der .NET-Welt zu verwenden. Das spezifische Problem beinhaltet späten Bindung Anrufe an IDispatch durchzuführen, ohne C # 4.0 zu benötigen. (Das heißt, während .NET 2.0 verwenden)

War es hilfreich?

Lösung 2

Späte gebunden IDispatch genannt ist relativly leicht in .NET, obwohl piss-poor:

public static void SpawnIEWithSource(String szHtml)
{
    // Get the class type and instantiate Internet Explorer.
    Type ieType = Type.GetTypeFromProgID("InternetExplorer.Application");
    object ie = Activator.CreateInstance(ieType);

    //Navigate to the blank page in order to make sure the Document exists
    //ie.Navigate2("about:blank");
    Object[] parameters = new Object[1];
    parameters[0] = @"about:blank";
    ie.GetType().InvokeMember("Navigate2", BindingFlags.InvokeMethod | BindingFlags.IgnoreCase, null, ie, parameters);

    //Get the Document object now that it exists
    //Object document = ie.Document;
    object document = ie.GetType().InvokeMember("Document", BindingFlags.GetProperty | BindingFlags.IgnoreCase, null, ie, null);

    //document.Write(szSourceHTML);
    parameters = new Object[1];
    parameters[0] = szHtml;
    document.GetType().InvokeMember("Write", BindingFlags.InvokeMethod | BindingFlags.IgnoreCase, null, document, parameters);

    //document.Close()
    document.GetType().InvokeMember("Close", BindingFlags.InvokeMethod | BindingFlags.IgnoreCase, null, document, null);

    //ie.Visible = true;
    parameters = new Object[1];
    parameters[0] = true;
    ie.GetType().InvokeMember("Visible", BindingFlags.SetProperty | BindingFlags.IgnoreCase, null, ie, parameters);
}

Die Frage verwiesen, so dass die ursprünglich „nicht möglich, bis C # 4.0“ wurde zu zeigen geändert, wie es möglich ist, in .NET 2.0.

Ist C # .NET-Unterstützung IDispatch späte Bindung?

Andere Tipps

  

Update: Auf der Grundlage Frage Updates habe ich die Teile meiner Antwort entfernt, die nicht mehr relevant für die Frage sind. Falls jedoch andere Leser für eine schnelle und schmutzige Art und Weise suchen HTML in einer WinForms-Anwendung zu erzeugen und benötigen keine In-Prozess-IE, ich gehe wie folgt vor:

Mögliches Szenario 1: Das ultimative Ziel ist HTML zu Ihren Endbenutzer einfach angezeigt werden und mit Windows Forms

System.Windows.Forms.WebBrowser ist der mühsam leicht .NET Wrapper für die Schnittstelle, die Sie manuell zu implementieren versuchen zu. Um es zu erhalten, per Drag & Drop eine Instanz dieses Objekt aus der Symbolleiste (gelistet als „Web-Browser“ unter dem „All Windows Forms“ Abschnitt) auf das Formular. Dann werden auf einem geeigneten Event-Handler:

webBrowser1.Navigate("about:blank");
webBrowser1.Document.Write("<html><body>Hello World</body></html>");

Bei meinem Test-App, diese korrekt angezeigt, die eindringliche Botschaft, die wir alle gelernt haben, zu fürchten und nur ungern.

Die Antworten in der Post, die Sie verlinken auf tatsächlich falsch. Im Allgemeinen ist es sehr einfach, mit IDispatch basierten Objekten in .net zu beschäftigen. Grundsätzlich geht man durch drei Schritte:

Die meisten Automatisierungsobjekte (wahrscheinlich weit über 90%), die als IDispatch Schnittstellen ausgesetzt sind, haben andere Schnittstellen, die durch nicht-Scripting-Typ COM-Clients verwendet werden können (entweder die IDispatch-Schnittstelle ist eigentlich eine vollständige COM-Schnittstelle, die von IDispatch oder das Objekt unterstützt ein oder mehrere andere IUnknown abgeleitet Schnittstellen). In diesem Fall würden Sie einfach die entsprechende COM-Schnittstelle Definition importieren und werfen dann das Objekt an die entsprechende Schnittstelle. Die Besetzung ruft Query-Interface unter der Decke und gibt einen umhüllten Verweis auf die Schnittstelle, die Sie wollen.

Dies ist die Technik, die Sie in dem Szenario verwenden würden, die Sie oben dargestellt. Das Document-Objekt, das von dem IE-Automatisierungsobjekt zurückgegeben wird, unterstützt die IHTMLDocument, IHTMLDocument2, IHTMLDocument3, IHTMLDocument4 und IHTMLDocument5 Schnittstellen (abhängig von der Version von Internet Explorer Sie verwenden). Sie sollten an die entsprechende Schnittstelle umgewandelt und dann die entsprechende Methode aufrufen. Zum Beispiel:

IHTMLDocument2 htmlDoc = (IHTMLDocument2)webDocument;
htmlDoc.Write(htmlString);
htmlDoc.Close();

In dem seltenen Fall, in dem das Automatisierungsobjekt nicht eine alternative Schnittstelle nicht unterstützt. Dann sollten Sie VB.Net verwenden diese Schnittstelle zu wickeln. Mit Option Strict auf OFF (für die Wrapper-Klasse nur) können Sie VB eingebaute Unterstützung nutzen zu spät gebunden Anrufe einfach auf die entsprechenden IDispatch Methoden unter der Decke nennen. In seltenen Fällen mit ungewöhnlichen Argumenttypen müssen Sie möglicherweise ein wenig mit dem Aufruf zur Geige, aber im Allgemeinen in VB können Sie es einfach! Auch bei den dynamischen Ergänzungen zu C # v4 VB wird wahrscheinlich immer noch eine signifikant bessere Unterstützung für spät gebundene COM-Aufrufe.

Wenn Sie aus irgendeinem Grund nicht VB verwenden, um die Automatisierungsschnittstelle wickeln, dann können Sie noch machen alle notwendigen Anrufe von C # mithilfe von Reflektion. Ich werde nicht ins Detail gehen, da diese Option sollte im Grunde nie hier verwendet werden, sondern ist ein kleines Beispiel rel="nofollow Amt beteiligt Automatisierung .

In diesem Artikel: http://www.codeproject.com/KB/cs/IELateBindingAutowod.aspx

Internet Explorer später Bindung Automation Durch yincekara

Internet Explorer Automatisierungsbeispielcode mit dem späten Bindung, ohne Microsoft.mshtml und Shdocvw Abhängigkeit.

für htmlDoc.write (htmlString); ändern

   [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);
        //void write([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] object[] psarray);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top