.NET2.0 C#Interop:如何从C#调用COM代码? [英] .NET2.0 C# Interop: How to call COM code from C#?

查看:510
本文介绍了.NET2.0 C#Interop:如何从C#调用COM代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我最后的开发环境中,我能够轻松地与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;
}

现在开始繁琐,痛苦的过程代码。



PInvoke.net已包含 IWebBrower2翻译,其重要性为:

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

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



我创建了COM类:

  [ComImport] 
[Guid(0002DF01-0000-0000-C000-000000000046)]
public class InternetExplorer $ b $所以现在是我的实际C#事务的时间:

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

//导航到about:blank以初始化浏览器
object o = System.Reflection.Missing.Value;
String url = @about:blank;
ie.Navigate2(ref url,ref o,ref o,ref o,ref o);

//将内容填入文档
object webDocument = ie.Document;
//webDocument.Write(szHtml);
//webDocument.Close();

ie.Visible = true;仔细的读者注意到,IWebBrowser2.Document是一个后期绑定的IDispatch。
}


$ b <
我们使用Visual Studio 2005,.NET 2.0和我们的客户的机器。



那么什么是.NET 2.0方法来调用方法对于某个级别上只支持后期绑定IDispatch的对象?



使用C#中的IDispatch快速搜索Stack Overflow会出现这篇文章说我想要的是不可能在.NET。



那么是否可以使用C#.NET 2.0中的COM?






问题是有一个公认的设计模式,我想在C#/ .NET中使用。它涉及到启动Internet Explorer的过程,并给它的HTML内容,所有而不使用临时文件。



一个被拒绝的设计理念是在WinForm上托管Internet Explorer。



一个可接受的替代方法是启动系统注册的Web浏览器,使其显示HTML,而不使用临时文件。



绊脚石继续在.NET世界中使用COM对象。具体的问题涉及到对IDispatch执行后期绑定调用,而不需要C#4.0。 (即使用.NET 2.0时)

解决方案

晚期绑定IDispatch调用在.NET中相对容易, / p>

  public static void SpawnIEWithSource(String szHtml)
{
//获取类类型并实例化Internet Explorer 。
Type ieType = Type.GetTypeFromProgID(InternetExplorer.Application);
object ie = Activator.CreateInstance(ieType);

//导航到空白页,以确保文档存在
//ie.Navigate2(\"about:blank);
Object [] parameters = new Object [1];
parameters [0] = @about:blank;
ie.GetType()。InvokeMember(Navigate2,BindingFlags.InvokeMethod | BindingFlags.IgnoreCase,null,ie,parameters);

//现在获取Document对象
// Object document = ie.Document;
object document = ie.GetType()。InvokeMember(Document,BindingFlags.GetProperty | BindingFlags.IgnoreCase,null,ie,null);

//document.Write(szSourceHTML);
parameter = 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;
parameter = 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后期绑定?


In my last development environment, I was able to easily interact with COM, calling methods on COM objects. Here is the original code, translated into C# style code (to mask the original language):

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

Now begins the tedious, painful, process of trying to interop with COM from managed code.

PInvoke.net already contains the IWebBrower2 translation, the relavent porition of which is:

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

I've created the COM class:

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

So now it's time for my actual C# transaction:

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

The careful readers notice that IWebBrowser2.Document is a late-bound IDispatch. We're using Visual Studio 2005, with .NET 2.0 on our, and our customer's, machines.

So what's the .NET 2.0 method to invoke methods on an object that, on some level, only supports late-bound IDispatch?

A quick search of Stack Overflow for using IDispatch from C# turns up this post saying what I want is not possible in .NET.

So is it possible to use COM from C# .NET 2.0?


The question is that there is an accepted design pattern that I want to use in C#/.NET. It involves launching Internet Explorer out of process, and giving it HTML content, all the while not using temporary files.

A rejected design idea is hosting Internet Explorer on a WinForm.

An acceptable alternative is launching the system registered web browser, giving it HTML to display, without using a temporary file.

The stumbling block is continuing to use COM objects in the .NET world. The specific problem involves performing late-binding calls to IDispatch without needing C# 4.0. (i.e. while using .NET 2.0)

解决方案

Late bound IDispatch called is relativly easy in .NET, although 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);
}

The referenced SO question that originally said "not possible until C# 4.0" was amended to show how it is possible in .NET 2.0.

Does C# .NET support IDispatch late binding?

这篇关于.NET2.0 C#Interop:如何从C#调用COM代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆