筆者在 ActiveX 控制項開發的封裝部署一文的最後,曾經提到 Windows XP 和 Windows Vista/7 的部署差異,這會讓開發人員需要依照作業系統的不同來撰寫 INF 檔案來自動化安裝,而且還要在網頁中偵測不同的作業系統給予不同的 CAB 檔案,但我們有一些方法來簡化這個部份的處理,讓開發人員可以在不動一行 <object> 宣告下,支援 Windows XP 和 Windows Vista/7 的作業系統環境。其實方法很簡單,只要使用 HTTP Handler 就能做到了。
筆者在 ActiveX 控制項開發的封裝部署一文的最後,曾經提到 Windows XP 和 Windows Vista/7 的部署差異,這會讓開發人員需要依照作業系統的不同來撰寫 INF 檔案來自動化安裝,而且還要在網頁中偵測不同的作業系統給予不同的 CAB 檔案,但我們有一些方法來簡化這個部份的處理,讓開發人員可以在不動一行 <object> 宣告下,支援 Windows XP 和 Windows Vista/7 的作業系統環境。其實方法很簡單,只要使用 HTTP Handler 就能做到了。
HTTP Handler 能夠輸出字串與二進位的資料流,並且重新設定用戶端瀏覽器可看到的 Content Type 型別,這樣的特性可以讓我們可以用 HTTP Handler 偽裝成 CAB 檔案,只要由 HTTP Handler 輸出 CAB 檔的資料流,並且將資料流的 Content Type 型別設為 application/vnd.ms-cab-compressed,即可在前端不做任何改變的情況下,就可以針對不同的作業系統輸出不同的 CAB 檔案。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
namespace MyWebApplication
{
public class MyControlInstallHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if (context.Request.Browser.ActiveXControls)
{
if ((context.Request.UserAgent.IndexOf("Windows NT 5.2") > 0) ||
(context.Request.UserAgent.IndexOf("Windows NT 5.1") > 0) ||
(context.Request.UserAgent.IndexOf("Windows NT 5.0") > 0))
{
// download CAB with autorun MSIEXEC engine for install sliently.
// Windows XP and 2000
context.Response.ContentType = "application/vnd.ms-cab-compressed";
context.Response.WriteFile(VirtualPathUtility.ToAbsolute("/cabs/ControlForNT5.cab"));
}
else
{
// download CAB with autorun setup.exe for install component interactively.
// Windows Vista or 7 or later version.
context.Response.ContentType = "application/vnd.ms-cab-compressed";
context.Response.WriteFile(VirtualPathUtility.ToAbsolute("/cabs/ControlForNT6.cab"));
}
}
else
{
context.Response.Write("E_ACTIVEX_CONTROL_NOT_SUPPORTED");
}
}
public bool IsReusable
{
get { return true; }
}
}
}
接著,在 Web.config 中設定,將 Cab 檔案指向 HTTP Handler:
<add verb="GET" name="MyControlInstaller" path="MyControl.cab" type="MyWebApplication.MyControlInstallHandler" />
然後在 HTML 中加入 <object> 標籤以使用 ActiveX Control:
<object classid="clsid:xxxxxxxx-xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" codebase="MyControl.cab"></object>
就可以使用了。