當 PHP 項目需要復用 C# 業務邏輯(加密算法、硬件交互、圖像處理等)時,可通過 COM 互操作調用 .NET 組件。本文記錄從 C# 類庫創建、強簽名、註冊 GAC 到 PHP 調用的完整流程(Windows 環境)。
HelloWorld。[ComVisible(true)](需 using System.Runtime.InteropServices;)。sn -k HelloWorld.snk // VS Developer Command Prompt專案屬性 → Signing → 勾選 Sign the assembly → 選擇
HelloWorld.snk。
namespace HelloWorld {
public class Hello {
public string Write() { return "Hello World"; }
}
}
bin/Release/HelloWorld.dll。以管理員身份運行 VS Developer Command Prompt:
cd /d D:\Path\To\HelloWorld\bin\Release regasm HelloWorld.dll // 註冊 COM gacutil /i HelloWorld.dll // 安裝到全局程序集緩存 (GAC)
關鍵點:
regasm 生成類型庫(.tlb)並寫入註冊表(HKCR\CLSID)。gacutil /i 使組件機器級可用,任意路徑下 PHP 均可調用。無強命名無法進 GAC。gacutil /l HelloWorld 列表中應顯示版本、公鑰標記。<?php
try {
$obj = new COM("HelloWorld.Hello"); // ProgID = 命名空間.類名
$result = $obj->Write();
echo $result; // 輸出: Hello World
} catch (com_exception $e) {
echo "COM Error: " . $e->getMessage();
// 常見錯誤: 類未註冊、架構不匹配(x86/x64)、權限不足
}
?>
| PHP 進程 | C# 組件 | 結果 | |
|---|---|---|---|
| x86 (32-bit) | x86 / Any CPU (Prefer 32-bit) | ✅ 正常 | |
| x64 (64-bit) | x64 / Any CPU (Prefer 32-bit=off) | ✅ 正常 | |
| x86 | x64 | ❌ Class not registered | |
| x64 | x86 | ❌ Class not registered |
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| COM 互操作 | 原生調用、性能較好 | 僅限 Windows、部署複雜、版本鎖定 | 緊耦合、高頻調用、需共享內存 |
命令行執行 exec() | 跨平台、語言無關、隔離性好 | 進程啟動開銷大、數據傳輸序列化 | 低頻、長耗時、獨立任務 |
| HTTP API (WebAPI/gRPC) | 標準化、跨語言、可擴展、易監控 | 網絡延遲、需維護服務 | 微服務架構、異構系統集成 |
| 消息隊列 (RabbitMQ/Kafka) | 解耦、削峰、可靠投遞 | 基礎設施複雜 | 異步任務、事件驅動 |