在我的最后一个开发环境,我能轻松地与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翻译,的relavent porition其是:

[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,和我们的客户,机器。

那么什么是.NET 2.0方法来调用对象的方法是,在一定程度上,仅支持后期绑定的IDispatch?

使用的IDispatch从C#快速搜索堆栈溢出的变成了此篇说我想要什么是不可能的.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

称为后期绑定的IDispatch是在.NET relativly容易,虽然小便-差:

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

引用的SO问题最初说“不可能直到C#4.0”进行了修改,以显示它是如何可能在.NET 2.0。

是否C#的.NET支持的IDispatch后期绑定?

其他提示

  

更新:基于问题的更新,我已删除不再相关的问题,我的答案的一部分。然而,如果其他读者正在寻找一个快速和肮脏的方式WinForms应用程序生成HTML和不需要在进程IE浏览器,我会留下以下内容:

<强>可能的方案1:最终的目标是简单地显示HTML给最终用户,并且使用Windows窗体

System.Windows.Forms.WebBrowser是您试图手动实现接口的苦心容易.NET包装。为了得到它,将它从工具栏(“所有Windows窗体”一节中列出的“Web浏览器”)到您的形式丢弃对象的实例。然后,在一些合适的事件处理程序:

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

在我的测试应用程序,这正常显示困扰的消息,我们都已经学会了恐惧和厌恶。

在您链接到后期的答案实际上是不正确。它通常是很容易对付的基于.NET的IDispatch的对象。基本上,你要经过三个步骤:

这被公开为IDispatch接口大部分自动化对象(可能超过90%)具有能够被非脚本型COM客户端使用(或者IDispatch接口实际上是从IDispatch接口或对象衍生的全COM接口以外的接口支持一个或多个其它的IUnknown衍生接口)。在这种情况下,您只需输入相应的COM接口定义,然后把对象到相应的接口。演员在幕后调用QueryInterface并返回一个包裹引用到你想要的界面。

这是你在你上文呈现的场景中使用的技术。即从IE自动化对象返回的文档对象支持IHTMLDocument,的IHTMLDocument2,IHTMLDocument3,IHTMLDocument4和IHTMLDocument5接口(取决于使用的是IE的版本)。您应该转换为相应的接口,然后调用相应的方法。例如:

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

在罕见情况下自动化对象不支持的替代接口。那么你应该使用VB.Net来包装接口。有了严格的选项设置为关闭(仅用于包装类),可以使用VB的内置支持后期绑定调用只需调用覆盖下的适当IDispatch方法。在极少数情况下不寻常的参数类型,你可能需要摆弄了一下与呼叫,但在一般情况下,在VB中你可以做到这一点!即使在动态添加到C#V4 VB仍将可能有后期绑定COM调用显著更好的支持。

如果由于某种原因,你不能用VB来包装自动化接口,那么你仍然可以从C#中使用反射任何必要的调用。我不会去到任何细节,因为这个选项应该基本上都不使用,但这里是一个小例子,涉及办公自动化

请参阅这篇文章: http://www.codeproject.com/KB/cs/IELateBindingAutowod.aspx

Internet Explorer中后期绑定自动化 通过yincekara

使用Internet Explorer自动化示例代码后期绑定,而不Microsoft.mshtml和SHDOCVW依赖性

有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