在我的上一个开发环境中,我能够轻松地与 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 翻译 http://pinvoke.net/default.aspx/Interfaces/IWebBrowser2.html,其中相关部分是:
[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)方法的方法是什么?
在 Stack Overflow 上快速搜索发现使用 C# 中的 IDispatch这个帖子 https://stackoverflow.com/questions/403218/does-c-net-support-idispatch-late-binding在.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 时)