C#外掛功能至外部程式

如果要將功能建立在別人主程式中,
除了將功能程式碼建立在對方程式碼內,
還可以使用以下這種將功能外掛的方式來達成目標
以下提供簡單範例

外部主程式

C#外掛功能至外部程式

建立一個按鈕至外部主程式,將兩者合併
C#外掛功能至外部程式

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
namespace UI_Reflash
{
    public partial class Form1 : Form
    {
        /* 參數初始化 */
        public  Process exe = null;
        public  IntPtr  MWH = IntPtr.Zero;   /* exe hwnd number */
        public Form1()
        {
            InitializeComponent();
        }
        /* 按鈕觸發啟動 */
        private void button1_Click(object sender, EventArgs e)
        {
            /* 按鈕功能觸發MessageBox */
            MessageBox.Show("UI合併觸發成功");
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            /* 隱藏UI */
            Hide();
            /* 執行主要框架的程式 */
            RunMainWindows();
            /* 獲得需連結的hwnd物件 */
            IntPtr mainHandle = UI.find_windows_use_process_name("ICOS_Simuation.exe");//主程式名稱
            if(mainHandle != IntPtr.Zero)
            {
                /* 獲得連結物件的hwnd */
                int mainHandle_ID_List = UI.find_Process_PID_use_process_name("ICOS_Simuation.exe");
                /* 設定視窗格式 */
                /* Form Border Style = 設定為 None */
                FormBorderStyle = FormBorderStyle.None;
                /* 設定按鈕顯示位置與大小 */
                SetBounds(0,110,40,40, BoundsSpecified.Location);
                /* 刷新UI介面 */
                Thread CT = new Thread(() =>
                {
                    this.Invoke((MethodInvoker)delegate
                    {
                        /* Set_UI_Interface(本體UI hwnd , 連結物件UI hwnd) */
                        UI.Set_UI_Interface(this.Handle, mainHandle);
                        Show(); //刷新顯示原本隱藏的視窗
                    });
                    MWH = mainHandle;
                    Thread.Sleep(100);
                    GC.Collect(); //強迫釋放資源
                });
                CT.Start();
            }
        }
        /* 使用process的方式 Run 主程式 ,並獲取需連結物件whnd */
        public void RunMainWindows()
        {
            System.Diagnostics.ProcessStartInfo Info = new System.Diagnostics.ProcessStartInfo();
            Info.FileName = @".ICOS_Simuation.exe"; //主程式檔名
            //Info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;   // 隱藏視窗
            exe = Process.Start(Info);
            MWH = exe.MainWindowHandle;
            Thread.Sleep(200);
        }
    }
}

UI.cs 檔案

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
/* point use */
using System.Drawing;
/* use Dll & ini */
using System.Runtime.InteropServices;
using System.Reflection;
using System.Management;
using System.IO;
using System.Diagnostics;
using System.Threading;
/* Array list */
using System.Collections;
using System.Threading;
namespace UI_Reflash
{
    class UI
    {
        /* 重設UI介面參數使用 */
        public static int GWL_STYLE = -16;
        public static int WS_CHILD = 0x40000000;
        /* 使用執行程式名稱尋找視窗物件 EX: process name = Mmi.exe*/
        public static IntPtr find_windows_use_process_name(string process_name)
        {
            Dictionary<int, Handler> getHandler = GetHandler();
            IntPtr hwnd = IntPtr.Zero;
            foreach (var p in getHandler)
            {
                String name = getHandler[p.Key].xInfo.Name;
                if (name == process_name)
                {
                    hwnd = getHandler[p.Key].hwnd;
                }
            }
            return hwnd;
        }
        /* 使用執行程式名稱尋找視窗物件 EX: process name = Mmi.exe  return PID */
        public static int find_Process_PID_use_process_name(string process_name)
        {
            Dictionary<int, Handler> getHandler = GetHandler();
            int pid_number = -1;
            foreach (var p in getHandler)
            {
                String name = getHandler[p.Key].xInfo.Name;
                if (name == process_name)
                {
                    pid_number = getHandler[p.Key].id.Id;
                }
            }
            return pid_number;
        }
        /// <summary>
        /// 列出目前全部使用中程式的 Handler 資訊
        /// </summary>
        public static Dictionary<int, Handler> GetHandler()
        {
            Dictionary<int, Handler> dic = new Dictionary<int, Handler>();
            foreach (Process proc in Process.GetProcesses())
            {
                try
                {
                    Handler tm = new Handler();
                    tm.id = proc;
                    tm.hwnd = proc.MainWindowHandle;
                    tm.xInfo = new FileInfo(proc.MainModule.FileName);
                    if (!dic.ContainsKey(proc.Id)) dic.Add(proc.Id, tm);
                }
                catch { }
            }
            return dic;
        }
        /* IntPtr guestHandle -> 要嵌入的元件   */
        /* IntPtr hostHandle  -> 被嵌入的主程式 */
        public static void Set_UI_Interface(IntPtr guestHandle, IntPtr hostHandle)
        {
            //調用windows·Api SetWindowLong 強制修改mdi的窗口屬性。
            Win32APi.SetWindowLong(guestHandle, GWL_STYLE, Win32APi.GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD);
            Win32APi.SetParent(guestHandle, hostHandle); //窗體崁入
        }
    }
}

當外部程式被執行起來就會顯示如下圖
將功能合併至主程式中
C#外掛功能至外部程式