.NET 補丁王 Harmony Library -- 簡介

Harmony 是一個 .NET 的開源 Runtime Patching 函式庫,由 Andreas Pardeike 開發,這個函式庫能夠在不具有原始碼的狀況下動態修改任何 .NET 方法的行為。這系列文章記錄一些關於這個函式庫的使用方式。

如何安裝
  1. 透過 Package Manager Console:輸入 Install-Package Lib.Harmony
  2. 透過圖形化介面:

 

補丁的種類

Harmony 提供多種補丁方式,每種都有不同用途:

  1. Prefix – 在原始方法執行前呼叫。
    •     改變或檢查原始方法的參數
    •     決定是否跳過原始方法
    •     設定狀態供 Postfix 使用
  2. Postfix – 在原始方法執行後呼叫。
    •     讀取或修改原始方法的回傳值
    •     存取原始方法的參數
    •     使用 Prefix 設定的狀態
  3. Transpiler – 不直接執行,而是修改原始方法的 IL 指令碼。適合進行進階的程式碼重寫。
  4. Finalizer – 在所有 Postfix 之後執行,並包裹 try/catch。
    •     保證某段程式碼一定會執行
    •     攔截或修改例外狀況
  5. Reverse Patch –  與其他不同,它是把「原始方法」補丁到你自己的方法 stub 上,方便在自訂程式碼中呼叫原始邏輯。
執行補丁的方式
  1. 手動補丁
    •     你自行取得 MethodInfo ,並用 HarmonyMethod 包裝後傳給 Patch()。
    •     方法名稱可自由,但必須是 static。
  2. 使用  annotation
    •     在類別上加上 HarmonyPatch  attribute。
    •     在類別中定義 Prefix、Postfix、Transpiler 等方法。
    •     方法名稱可用 attribute 指定,例如 HarmonyPostfix attribute。
適用的技術情況
  1. 無法修改原始程式碼:例如第三方 DLL、Unity 遊戲、封閉的 API。
  2. 需要在方法執行前後插入邏輯:紀錄日誌、驗證輸入、修改回傳值。
  3. 要完全跳過某個方法:Prefix 可直接 return false。
  4. 要修改 IL 指令碼:Transpiler 可進行進階程式碼重寫。
  5. 要呼叫私有方法或取得原始邏輯:Reverse Patch 可直接嵌入原始方法,不需反射。
  6. 要呼叫原始方法但稍微改寫:Transpiled Reverse Patch 可先用 Transpiler 改 IL,再嵌入。
使用限制
  1. 補丁方法必須是靜態方法
    Prefix、Postfix、Transpiler、Finalizer、Reverse Patch 等補丁方法都必須宣告為 ,因為 Harmony 只能儲存方法指標,無法管理執行個體。
  2. 僅能在目前 應用程式定義域 (AppDomain) 中運作
    Harmony 的補丁無法跨越 AppDomain,因此在某些特殊環境(例如多 AppDomain 的應用程式)可能受限。
  3. 泛型支援有限
    雖然 Harmony 可以補丁泛型方法,但支援仍屬實驗性,某些情況下可能會失敗或行為不一致。
  4. 方法被編譯器 inline 時可能失效
    如果目標方法被 JIT 編譯器或 C# 編譯器內聯 (inline),Harmony 就無法攔截它。
  5. 僅能補丁 IL 方法
    Harmony 依靠 IL 指令碼修改,因此無法補丁某些特殊方法(例如純原生程式碼、P/Invoke)。
  6. 與其他補丁或工具衝突
    如果同一方法被多個補丁或其他工具修改,可能會出現衝突或執行順序問題。
  7.  需要正確的簽名匹配
    補丁方法的參數必須與目標方法相符,否則 Harmony 無法正確注入。
資料來源

對於 Harmony Library 的簡單介紹到這裡,下一篇開始介紹實作的流程。