【BCB5】【C#.Net】BCB5 使用 C# .Net 建立的 DLL

  • 3099
  • 0
  • 2018-04-17

由於經常有舊專案要新增與新專案相同的功能,但舊專案使用 BCB5 開發,新專案使用 C# .Net 開發,開發環境的不同,使得相同功能需要重複撰寫,造成重工的問題,而且有些新功能在 BCB5 本身不支援,因此必須使用 C# .Net 來開發給 BCB5 使用,但 BCB5 並無法直接使用 C# .Net 建立的 DLL,必須以 COM 元件的方式提供使用,所以,特以此篇做 Demo 說明。

C# .Net 如何建立 COM 元件

開發環境說明:

  1. 作業系統:Win10
  2. IDE:VS2012
  3. .Net Framework:4.5

作為 COM 元件的專案,有以下幾點須注意:

  1. AssemblyInfo.cs - [assembly: ComVisible(true)]
  2. 屬性 -> 建置 -> 輸出 -> 勾選 "註冊 COM Interop"
  3. 宣告 interface 提供給接口 class 繼承。
  4. 接口的 interface 與 class 需給予 GUID。(工具 -> 建立 GUID)
另外一點,因為需要註冊 COM 元件,所以 VS2012 必須選擇以 "系統管理員身分執行" 的方式開啟。

以下範例以 COM_4_BCB_DEMO 為方案名稱,內有兩個專案,分別為 COM4BCB 與 FuncFactory,其中 COM4BCB 為接口類別,FuncFactory 為實作類別,也就是說 COM4BCB.dll 必須參考到 FuncFactory.dll,但在 BCB5 只看得到 COM4BCB interface 提供的介面函式,會這樣做是因為這樣必較接近實際專案的開發模式,總不能為了做成 COM 元件,就把所有的東西都寫在一個專案內吧,這樣也太不實際了。

簡述步驟與程式碼:

  1. 建立 Windows 類別庫
  2. 設定 COM4BCB 專案屬性
  3. 設定 COM4BCB 專案的 AssemblyInfo.cs -> assembly: ComVisible(true)
  4. 新增 FuncFactory 專案
  5. 程式碼內容如下:
    //COM4BCB.cs
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using FuncFactory;
    using System.Runtime.InteropServices;   //作為 COM 元件的專案必需引用
    
    namespace COM4BCB
    {
    
        [Guid("8791D490-F0B1-4198-9582-2DDE3EA4AD64")]
        public interface ICOM4BCBInterface
        {
            [DispId(1)]
            int Add(int x, int y);
    
            [DispId(2)]
            int Sub(int x, int y);
    
            [DispId(3)]
            string GetComInfo();
    
            [DispId(4)]
            void ShowMsg(string name);
        }
    
        [Guid("009E0FB6-BF2E-4C32-BAAF-5BD38E7B1CCC")]
        public class COM4BCBDemo : ICOM4BCBInterface
        {
    
            private DemoFunc demo = new DemoFunc();
    
            public int Add(int x, int y)
            {
                return demo.Add(x, y);
            }
    
            public int Sub(int x, int y)
            {
                return demo.Sub(x, y);
            }
    
            public string GetComInfo()
            {
                return demo.GetComInfo();
            }
    
            public void ShowMsg(string s)
            {
                demo.ShowMsg(s);
            }
        }
    }
    
    //FuncFactory.cs
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace FuncFactory
    {
    
        public class DemoFunc
        {
            public DemoFunc()
            {
            }
    
            public int Add(int x, int y)
            {
                return (x + y);
            }
    
            public int Sub(int x, int y)
            {
                return (x - y);
            }
    
            public string GetComInfo()
            {
                return "測試於 BCB5 呼叫使用 C# .Net DLL。";
            }
    
            public void ShowMsg(string s)
            {
                MessageBox.Show(s);
            }
        }
    }
    

     

  6. 設定 GUID。
  7. 建置方案後,可於 COM_4_BCB_DEMO\COM4BCB\bin\Debug\ 底下得到 COM4BCB.dll, COM4BCB.tlb 與 FuncFactory.dll,將這三個檔案放置於 BCB 專案執行檔同目錄底下。

註冊 COM 元件

  1. 複製 C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe 檔案至 BCB 專案執行檔同目錄底下。
  2. 建立批次檔 RegAsm.bat 於 BCB 專案執行檔同目錄底下,批次檔內容可參考下方所示:
    @echo off
    %~dp0RegAsm.exe COM4BCB.dll
    pause

     

  3. 以系統管理員的身分執行,執行後出現以下畫面代表註冊成功。

BCB5 如何引用 COM 元件

測試環境說明:

  1. 作業系統:Win10
  2. IDE:BCB5
  3. .Net Framework:4.5 (務必安裝 Microsoft .NET Framework,且版本需與 COM 的開發環境版本相同 )

簡述步驟與程式碼:

  1. 產生 COM 代理類別 Unit:開啟 BCB5 IDE 選擇 Project -> Import Type Library -> 選擇 COM4BCB.tlb -> 如下圖選擇 -> Create Unit -> 產生 COM4BCB_TLB.cpp 與 COM4BCB_TLB.h (還有一些阿浬阿渣的檔案)。
  2. 開啟 COM4BCB_TLB.h 觀察 GUID 的內容,會發現與 C# .Net 設定的不同,所以必須手動修改成與 C# .Net 設定相同的 GUID 後才可使用。
  3. 建立新的 BCB5 專案,本例專案名稱為 ComImport,將方才產生的 Unit - COM4BCB_TLB 加入專案中,並於引用的 Form 或 Unit 中加入 #include "COM4BCB_TLB.h"。
  4. 本利使用的 Sample Code 如下:
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
        HRESULT hr;
        Com4bcb_tlb::ICOM4BCBInterfacePtr ptr;
        CoInitialize ( NULL );  //初始化 COM 元件
        hr = ptr.CreateInstance(__uuidof (Com4bcb_tlb::COM4BCBDemo));   //建立 COM 物件
        if(hr == S_OK)  //若 COM 物件建立失敗會回傳小於 0 的值(錯誤碼)
        {
            AnsiString s0 = ptr->GetComInfo();
            ptr->ShowMsg(WideString(s0));
            AnsiString s1 = "1 加 2 等於 " + IntToStr(ptr->Add(1, 2));
            ptr->ShowMsg(WideString(s1));
            AnsiString s2 = "1 減 2 等於 " + IntToStr(ptr->Sub(1, 2));
            ptr->ShowMsg(WideString(s2));
        }
    }
    

     

  5. 執行結果如下所示:

結語

之後如果 C# .Net 的實作內容有變更,只要 interface 沒有變,直接替換 dll 即可,程式不用再重新編譯,這是使用 dll 的好處,更重要的是專案只要維護 C# 版本即可,不用重複撰寫相同功能的 Code,只為了配合不同的 IDE 開發環境,這才是最重要的。

參考

  1. BCB6 调用C# DLL