3

前回の開発環境では、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 translationが含まれており、その関連部分は次のとおりです。

[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 であることに気付きます。私たちは Visual Studio 2005 を使用し、.NET 2.0 を私たちのマシンと顧客のマシンで使用しています。

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

C# から IDispatch を使用するために Stack Overflow をすばやく検索すると、この投稿が表示され、私が望むことは .NET では不可能であると書かれています。

C# .NET 2.0 から COM を使用することは可能ですか?


問題は、C#/.NET で使用したい、受け入れられているデザイン パターンがあるかどうかです。Internet Explorer をアウト プロセスで起動し、HTML コンテンツを提供しますが、一時ファイルは使用しません。

却下された設計案は、WinForm で Internet Explorer をホストすることです。

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

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

4

4 に答える 4

4

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

考えられるシナリオ 1: 最終的な目標は、Windows フォームを使用しているエンド ユーザーに単純に HTML を表示することです。

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

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

私のテストアプリでは、これは私たち全員が恐れて嫌うことを学んだ忘れられないメッセージを正しく表示しました.

于 2009-01-23T04:04:47.813 に答える
3

呼び出されるレイト バインド IDispatch は、.NET では比較的簡単ですが、小便は貧弱です。

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

「C# 4.0 までは不可能」と最初に述べた参照されている SO の質問は、.NET 2.0 でどのように可能であるかを示すように修正されました。

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

于 2009-01-29T19:28:49.257 に答える
0

この記事を参照してください:http: //www.codeproject.com/KB/cs/IELateBindingAutowod.aspx

InternetExplorerの遅延バインディングの自動化byyincekara

Microsoft.mshtmlおよびshdocvwに依存しない、遅延バインディングを使用したInternetExplorer自動化サンプルコード。

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);
于 2009-06-18T11:53:04.987 に答える
0

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

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

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

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

まれに、自動化オブジェクトが代替インターフェイスをサポートしていない場合。次に、VB.Net を使用してそのインターフェイスをラップする必要があります。Option Strict をオフに設定すると (ラッパー クラスのみ)、VB のビルトイン サポートを使用して、適切な IDispatch メソッドを内部で呼び出すことができます。例外的な引数タイプのまれなケースでは、呼び出しを少しいじる必要があるかもしれませんが、一般的に、VB ではそれを行うことができます! C# v4 VB に動的に追加されたとしても、遅延バインド COM 呼び出しのサポートが大幅に向上する可能性があります。

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

于 2009-01-29T18:49:06.200 に答える