ISAPI (Internet Server API) 是 IIS 早期高效能擴展技術:**DLL 常駐記憶體、無進程建立開銷**、比 CGI 快數十倍。雖然現代已轉向 ASP.NET Core / Node.js,但理解 ISAPI 有助於維護舊系統、掌握 **原生 HTTP 伺服器擴展模型**。本文基於 VC6 MFC ISAPI Wizard 完整演示。
| 維度 | CGI | ISAPI |
|---|---|---|
| 進程模型 | 每請求建立新進程 | DLL 載入 IIS 進程,常駐 |
| 效能 | 低 (進程建立/銷毀、環境變數傳遞) | 高 (執行緒池、記憶體共享) |
| 狀態保持 | 困難 (需外部儲存) | 容易 (全域/靜態變數、記憶體快取) |
| 開發語言 | 任意 (Perl, C, VB...) | C/C++ (需編譯為 DLL) |
| 除錯難度 | 低 (獨立進程) | 高 (需附加至 IIS 進程) |
BEGIN_PARSE_MAP(CHelloWebExtension, CHttpServer)
ON_PARSE_COMMAND(Default, CHelloWebExtension, ITS_EMPTY)
// 自訂命令範例:
// ON_PARSE_COMMAND(ShowTime, CHelloWebExtension, ITS_EMPTY)
// ON_PARSE_COMMAND_PARAMS(Echo, CHelloWebExtension, ITS_STRING)
DEFAULT_PARSE_COMMAND(Default, CHelloWebExtension)
END_PARSE_MAP(CHelloWebExtension)
void CHelloWebExtension::Default(CHttpServerContext* pCtxt) {
StartContent(pCtxt); // 寫入
WriteTitle(pCtxt, _T("Hello Web"));
*pCtxt << _T("Hello from ISAPI Extension!");
EndContent(pCtxt); // 寫入
}
void CHelloWebExtension::ShowTime(CHttpServerContext* pCtxt) {
StartContent(pCtxt);
WriteTitle(pCtxt, _T("Server Time"));
CTime t = CTime::GetCurrentTime();
*pCtxt << t.Format(_T("%Y-%m-%d %H:%M:%S"));
EndContent(pCtxt);
}
| 錯誤 | 原因 | 對策 |
|---|---|---|
| Server Error 500: Specified module not found | 動態連結 MFC 但目標機無 MFC DLL | |
| 斷點不命中 | DLL 未重新載入 / PDB 不匹配 | |
| 存取違規 | 執行緒安全 / 全域資料競爭 | |
| 中文亂碼 | 未設定 Content-Type charset |
ISAPI 是 **「DLL 常駐、執行緒服務、Parse Map 路由」** 的經典模式,深刻影響了後世所有原生 HTTP 伺服器框架。維護舊專案時,請記住:**除錯附加 inetinfo.exe、靜態連結 MFC、執行緒安全第一**。新專案請毫不猶豫選擇 ASP.NET Core 或跨平台替代方案——**致敬經典,但不停留在過去**。