質問

前回の開発環境では、COMオブジェクトのメソッドを呼び出して、COMと簡単にやり取りすることができました。元のコードをC#スタイルのコードに変換します(元の言語をマスクするため):

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;
}

今、マネージコードからCOMとの相互運用を試みる退屈で苦痛なプロセスを開始します。

PInvoke.netには既に IWebBrower2の翻訳が含まれています。これは:

[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; }
}

COMクラスを作成しました:

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

これで、実際のC#トランザクションの時間です:

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;
}

注意深い読者は、IWebBrowser2.Documentが遅延バインディングのIDispatchであることに気付きます。 私たちとお客様のマシンに.NET 2.0を搭載したVisual Studio 2005を使用しています。

では、あるレベルでは遅延バインディングのIDispatchのみをサポートするオブジェクトのメソッドを呼び出す.NET 2.0メソッドは何ですか?

C#からIDispatchを使用するためにStack Overflowをすばやく検索すると、この投稿が表示されます .NETでは、欲しいものを言うことはできません。

では、C#.NET 2.0からCOMを使用できますか?


問題は、C#/。NETで使用したい承認済みのデザインパターンがあることです。一時ファイルを使用せずに、アウトオブプロセスでInternet Explorerを起動し、HTMLコンテンツを提供する必要があります。

拒否されたデザインアイデアは、WinFormでInternet Explorerをホストしています。

許容される代替手段は、システムに登録されたWebブラウザーを起動し、一時ファイルを使用せずにHTMLを表示することです。

つまずきのブロックは、.NETの世界でCOMオブジェクトを使用し続けています。特定の問題には、C#4.0を必要とせずにIDispatchの遅延バインディング呼び出しを実行することが含まれます。 (つまり、.NET 2.0の使用中)

役に立ちましたか?

解決 2

.NETで呼び出されるレイトバインドIDispatchは比較的簡単ですが、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);
}

元々は<!> quot; C#4.0 <!> quotまでは不可能だったと言っていた、参照されているSOの質問。 .NET 2.0で可能なことを示すために修正されました。

C#.NETはIDispatch遅延バインディングをサポートしていますか

他のヒント

  

更新:質問の更新に基づいて、質問に関連しなくなった回答の部分を削除しました。ただし、他の読者がwinformsアプリでHTMLを迅速かつダーティに生成する方法を探していて、インプロセスIEを必要としない場合は、以下を残します。

可能なシナリオ1:最終的な目標は、エンドユーザーにHTMLを表示し、Windowsフォームを使用することです

System.Windows.Forms.WebBrowserは、手動で実装しようとしているインターフェイスの骨の折れるほど簡単な.NETラッパーです。取得するには、そのオブジェクトのインスタンスをツールバー(<!> quot; Web Browser <!> quot; <!> quot; All Windows Forms <!> quot;セクションの下にリストされている)からフォームにドラッグアンドドロップします。 。次に、適切なイベントハンドラーで:

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

テストアプリでは、これは私たち全員が恐怖と嫌悪を覚えた忘れられないメッセージを正しく表示しました。

リンク先の投稿の回答は実際には間違っています。通常、.NetのIDispatchベースのオブジェクトを扱うのは非常に簡単です。基本的に、次の3つの手順を実行します。

IDispatchインターフェイスとして公開されるほとんどのオートメーションオブジェクト(おそらく90%を超える)には、非スクリプト型のCOMクライアントが使用できる他のインターフェイスがあります(IDispatchインターフェイスは、実際にはIDispatchまたはオブジェクトから派生した完全なCOMインターフェイスです) 1つ以上の他のIUnknown派生インターフェイスをサポートします)。この場合、適切なCOMインターフェイス定義をインポートし、オブジェクトを適切なインターフェイスにキャストするだけです。キャストは、カバーの下でQueryInterfaceを呼び出し、必要なインターフェイスへのラップされた参照を返します。

これは、上記で示したシナリオで使用する手法です。 IEオートメーションオブジェクトから返されるDocumentオブジェクトは、IHTMLDocument、IHTMLDocument2、IHTMLDocument3、IHTMLDocument4、およびIHTMLDocument5インターフェイスをサポートしています(使用しているIEのバージョンによって異なります)。適切なインターフェイスにキャストしてから、適切なメソッドを呼び出す必要があります。例:

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

まれに、オートメーションオブジェクトが代替インターフェイスをサポートしない場合。次に、VB.Netを使用してそのインターフェイスをラップする必要があります。 Option Strictをoffに設定すると(ラッパークラスのみ)、VBの遅延バインド呼び出しのサポートを使用して、適切なIDispatchメソッドを単純に呼び出すことができます。まれに、異常な引数タイプがある場合、呼び出しを少し調整する必要があるかもしれませんが、一般に、VBではそれを行うことができます! C#v4 VBに動的に追加された場合でも、レイトバウンドCOM呼び出しのサポートが大幅に改善される可能性があります。

何らかの理由でVBを使用してオートメーションインターフェイスをラップできない場合、リフレクションを使用してC#から必要な呼び出しを行うことができます。このオプションは基本的に使用されるべきではないため、詳細は説明しませんが、ここでは Officeに関する小さな例を示します。自動化

この記事を参照: http://www.codeproject.com/KB/cs/IELateBindingAutowod.aspx

Internet Explorer Late Binding Automation によってyincekara

Microsoft.mshtmlおよびshdocvwに依存せずに、遅延バインディングを使用するInternet Explorerオートメーションサンプルコード。

htmlDoc.write(htmlString); 変更

   [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);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top