書小宅之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();
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章