书小宅之C#——调用COM组件

.NET 平台下提供了COM Interop,即COM互操作技术,来解决在.NET中的托管代码能够使用COM组件和向CMO组件功能托管对象的问题。

首先,想要在.net中使用COM对象,需要找到要使用的COM 组件并注册它。使用 regsvr32.exe 注册或注销 COM DLL。

在项目文件名上右击->引用->添加引用-> .net/Com 下找到对应的组件【如添加Microsoft.Office.Interop.Word 14.0.0.0的引用 】
系统自带或一些驱动的dll一般在程序集,项目生成的dll一般在解决方案,DLL文件一般放在Bin目录下。

1、(一般电脑上下载了相关的组件,在注册表中中注册DUID项的在Com里都能找到)。
2、com组件有独立的类型库文件,基于接口进行通信,是非托管对象,可以不需要.net框架而直接运行;Com组件每次只能注册一个版本。
3、.net框架组件是托管对象,通过使用程序集清单来进行自我引用,这个程序集中包含了COM组件中定义的类型的元数据,不通过中间接口查询可直接通信,必须有.net框架的支撑才能运行。.net组件可以并存添加。

COM(组件对象模型)对象的调用,(.NET 框架中通过COM Interop支持)通过RCW【Runtime Callable Wrapper运行时可调用包装】来完成的,RCW中包含了包装COM组件中的类和接口,其工作主要有激活COM对象和在托管代码(.net平台)和非托管代码(Com组件)之间进行数据封送处理。

**数据封送**是——在托管代码中对非托管函数进行互操作时,需要通过方法的参数和返回值在托管内存和非托管内存之间传递数据的过程,数据封送处理的过程是由CLR(公共语言运行时)的封送处理服务(即封送拆送器)完成的。关于此相关内容可参见:书小宅之C#——调用Win32 API函数来说明托管代码中函数原型的定义
在这里插入图片描述

using System.Runtime.InteropServices; // 用 DllImport 需用此命名空间,Com互操作服务
//由于托管代码中不能直接使用COM对象和接口,所以托管代码对COM对象的调用时是通过CLR的 COM Interop 层作为代理完成的

在VS中为.NET 项目添加对应的COM组件的引用,此时VS就会自动将COM类型库中的COM类型库转化为程序集中的元数据。

引用后在项目的Bin>debug目录下可以看到相应的.dll动态链接库文件(互操作程序集),在打包程序的时候也必须将这些动态库文件一起打包,系统的功能才能正常使用。

代码来源

using System;
using Microsoft.Office.Interop.Word;
using System.IO;
using System.Runtime.InteropServices;

namespace COM互操作性
{
    class Program
    {
        static void Main(string[] args)
        {
            CreateWordDocument();// 调用COM对象来创建Word文档
            
            string wordPath = @"D:\test.docx";// 打开存在的文档插入文本
            OpenWordDocument(wordPath);
            Console.Read();
        }

        private static void CreateWordDocument()
        {
            // 启动Word并使Word可见
            Application wordApp = new Application() { Visible = true };
            wordApp.Documents.Add();// 新建Word文档
            Document wordDoc = wordApp.ActiveDocument;
            Paragraph para = wordDoc.Paragraphs.Add();
            para.Range.Text = "欢迎你,进入Learning Hard博客";
            // 保存文档
            object filename = @"D:\learninghard.doc";
            wordDoc.SaveAs2(filename);
            wordDoc.Close();// 关闭Word
            wordApp.Application.Quit();
        }
        // 向现有文档插入文本
        private static void OpenWordDocument(string wordPath)
        {
            // 启动Word 应用程序
            Application wordApp = new Application() { Visible = true };
            Document wordDoc=null;
            try
            {
                // 如果文档不存在时,就会出现调用COM对象失败的情况
                // 打开Word文档
                wordDoc = wordApp.Documents.Open(wordPath);
                // 向Word中插入文本
                Range wordRange = wordDoc.Range(0, 0);
                wordRange.Text = "这是插入的文本";
                // 保存文档
                wordDoc.Save();
            }
            catch(Exception ex)
            {          
                // 获得异常相对应的HRESULT值
                // 因为COM中根据方法返回的HRESULT来判断调用是否成功的
                int HResult = Marshal.GetHRForException(ex);
                // 设置控制台的前景色,即输出文本的颜色
                Console.ForegroundColor = ConsoleColor.Red;
                // 下面把HRESULT值以16进制输出,HResult是Com代码中返回的
                Console.WriteLine("调用抛出异常,异常类型为:{0}, HRESULT= 0x{1:x}", ex.GetType().Name, HResult);
                Console.WriteLine("异常信息为:" + ex.Message.Replace('\r', ' '));
            }
            finally
            {
                // 关闭文档并
                if (wordDoc != null)
                {
                    wordDoc.Close();
                }
                // 退出Word程序
                wordApp.Quit();
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章