2008年11月9日 星期日

[Plugin] 如何寫一個最簡單的 INF 檔

snap003

如果你寫的是 ActiveX 元件, 而且希望將一堆相關的 dll 複製到使用者電腦的 c:\windows\system32\自訂的目錄, 你就要會寫 INF.

INF 檔全名是 information file , 裡面放著如何安裝你的軟体在使用者電腦的指令. 基本上, IE 3.0 以後的瀏覽器都是用 Internet Component Download 這個 service 自動安裝你的 ActiveX 軟体, 而這個 service 吃的就是 INF 檔.

詳細說明: http://msdn.microsoft.com/en-us/library/aa741213(VS.85).aspx

本文大綱

  1. 最簡單 INF 檔寫作範例
  2. 最簡單建立 CAB 檔範例

開始

C & C++ 的程式設計師都知道每一個程式都有一個進入點, 也就是第一個執行的函式. 那麼 INF 檔的 main 是哪一個呢?

是這樣的.

如果你的 INF 檔沒有 [Add.Code] and [Setup Hooks] 那就會找 [DefaultInstall] section 開始執行

我們今天用 [DefaultInstall] 的方法, 主要原因是 standard Microsoft Win32 INF file 提供更有彈性的功能. 所以下面的 inf 檔裡面沒有 [Add.Code] 與 [Setup Hooks] sections.


現在開始動手吧.
我希望當使用者安裝我的 ActiveX 元件時, 做下面工作 ...

1. 把 a.dll, b.dll, c.ocx 複製到 c:\windows\system32\jing 目錄中
2. 把 JingPlugin1.dll 與 JingPlugin2.dll 複製到 c:\windows\system32\jing\plugins
3.
若使用者沒有這兩個目錄, 系統必須要自己建立
4. b.dll 與 c.ocx 必須註冊, 而且 b.dll 必須先註冊然後才是 c.ocx

最簡單 INF 檔寫作範例

; ---------------------------- d.inf ------------------------
; 這個 inf 檔必須要放在 cab 檔裡面一起散佈出去

[version]
signature=$Chicago$
AdvancedINF=1.0

; Step 1: (這是註解) INF file 的第一個執行指令
; CopyFiles = 要複製的檔案列表 sections
; RegisterOCXs = 要註冊的檔案列表 (你的元件可能有一堆 dll 或 ocx 要註冊)

[DefaultInstall]
CopyFiles= MyFiles, MyInf, PluginFileList
RegisterOCXs=RegisterOCXSection

; Step 2: 指定這些檔案要複製的目的地
; INF 中的號碼意義: see http://www.osronline.com/ddkx/install/create-inf_3aav.htm

[DestinationDirs]
; 在 MyFiles的檔案, 全部裝到 c:\Windows\system32\jing
; 目錄裡面 (11 對應到 system32)

MyFiles=11,jing ; 你看的沒錯, 就是 11,jing

; 在 MyInf 描述的檔案, 全部裝到 c:\Windows\Inf 裡面
MyInf=17

; 把 PluginFileList 描述的檔案, 全部倒進
; c:\Windows\system32\jing\plugins 裡面

PluginFileList=11,jing\plugins ; 同樣的 11,jing\plugins

; 如果要把一堆檔案放到任意位置, 則使用 -1即可

; 例如: 下面的指令會把 PluginFileList 的一堆檔案放到 c:\jing\plugins 裡面

; PluginFileList=-1,c:\jing\plugins

; Step 3: 定義 MyFiles 中包含哪些檔案
[MyFiles]

a.dll=a.dll ; a.dll 檔案的詳細資料, 參考 a.dll 描述
b.dll=b.dll ; b.dll 檔案的詳細資料, 參考 b.dll 描述
c.ocx=c.ocx ; c.ocx 檔案的詳細資料, 參考 c.ocx 描述

[a.dll] ; a.dll 描述
file=thiscab ; 這個檔案從目前的 cab 檔解析出來
FileVersion=0,0,0,0
;DestDir=11 ; 這個檔案要複製到 C:\Windows\system32 但適用於 [Add.Code ] 的方式, 目前使用 standard Microsoft Win32 INF file 的方式進行描述, 所以 DestDir 指令無效.

[b.dll] ; b.dll 描述
file=thiscab ; 這個檔案從目前的 cab 檔解析出來
FileVersion=0,0,0,0
RegisterServer=yes

[c.ocx] ; c.ocx 描述
file=thiscab ; 這個檔案從目前的 cab 檔解析出來
FileVersion=0,0,0,0
RegisterServer=yes

; Step 4: 定義 MyInf 中包含哪些檔案
[MyInf]
d.inf=d.inf ; d.inf 檔案的詳細資料, 參考 d.inf描述

[d.inf] ;d.inf 檔案的詳細描述
file-win32-x86=thiscab
FileVersion=1,0,0,0

; Step 5: 定義 PluginFileList 中包含哪些檔案
[PluginFileList]
JingPlugin1.dll=JingPlugin1.dll ; 詳細資料, 參考 JingPlugin1.dll描述
JingPlugin2.dll=JingPlugin2.dll ; 詳細資料, 參考 JingPlugin2.dll描述
[JingPlugin1.dll]
file=thiscab ; 這個檔案從目前的 cab 檔解析出來
FileVersion=0,0,0,0
[JingPlugin2.dll]
file=thiscab ; 這個檔案從目前的 cab 檔解析出來
FileVersion=0,0,0,0


; Step 6: 要註冊的全部放在這裡
[RegisterOCXSection]
"%11%\jing\b.dll" ; 自動註冊放在 system32\jing 裡面的 b.dll
"%11%\jing\c.ocx" ; 自動註冊放在 system32\jing 裡面的 c.ocx

; ---------------------------- end of d.inf ------------------------

最簡單建立 CAB 檔範例: 製作 cab 檔, 把你的 ActiveX 元件散佈出去

Step 1: 假設你的元件檔案結構如下:

a.dll
b.dll
c.ocx
d.inf
plugins
|______ JingPlugin1.dll
|______ JingPlugin2.dll

Step 2: 下達壓縮指令
"C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin\cabarc.exe" -r -s 6144 n my.cab c.ocx d.inf a.dll b.dll plugins\*.dll
Note:

1. 你不能用 -p 的方式建立 cab, 否則當安裝時, 會找不到子目錄裡面的檔案
2. 6144 是留給將來數位簽章使用的空間

Step 3: 完成產生 my.cab

Enjoy. 希望對你有幫助.

by Jing

延伸閱讀

[1] Using INF Files
[2] 一堆 INF 檔可用的指令

[3] Jing, "如何產生 certification 文件, 用來 sign 你的軟體?," 2009/5
http://mqjing.blogspot.com/2009/05/certification-sign.html

[4] Jing, "如何為你的 ActiveX 元件 (cab 檔) 加入數位簽章 -- signtool?," 2009/3
http://mqjing.blogspot.com/2009/03/plugin-activex-cab-signtool.html

[5] Jing, "ActiveX 元件版本問題," 2009/3
http://mqjing.blogspot.com/2009/03/plugin-activex.html

[6] Jing, "INF 檔裡面可不可以使用變數?," 2009/3
http://mqjing.blogspot.com/2009/03/plugin-inf.html


11 則留言:

  1. 您好:
    在偶然的機會拜讀您的文章,感覺您應該是這個領域的箇中高手,我個問題一直困擾著我,想請教您.
    在VB6時我們可以撰寫ActiveX 把它包成 *.CAB 然後寫個 HTML檔即可在IE Browser 執行,在 vb.net 2003 以後的版本好像已經沒有*.ocx 或 active X 這類專案開發.而我是使用VB.NET 2005 開發程式,於是我只要在userControl 裡加上一段
    Private DocVal As mshtml.IHTMLDocument2 = New mshtml.HTMLDocument
    Public Property Doc() As mshtml.HTMLDocument
    Get
    Return DocVal
    End Get
    Set(ByVal Value As mshtml.HTMLDocument)
    DocVal = Value
    End Set
    End Property

    然後在HTML 裡加
    < script>
    function loadDoc()
    {
    //passing the document as a parameter to our UserControl
    autoIE2.doc = document;
    }
    < /script>
    < /HEAD>
    < BODY onload=loadDoc() topmargin="0" leftmargin="0">
    < OBJECT id=autoIE2 classid="myduty.dll#dutyFrm">
    < /OBJECT>

    即可像VB6 執行 activeX 的效果,問題是在Intranet時執行效能很OK ,但是只要從遠端連VPN執行時效能奇差;後來有想到是否可以向VB6時把程式包成.CAB來執行,不知道您有什麼好建議 謝謝!
    email: taylor.wang@msa.hinet.net

    回覆刪除
  2. 你好,

    如果是網路傳輸效能的話, 確實會比較好.
    因為 CAB 是壓縮檔格式.

    下面是最簡單的範例: (已經使用最高壓縮倍率設定)

    手動製作 cab 檔設定指令
    "C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin\cabarc.exe" -m LZX:21 -r -s 6144 n 你的.cab 你的activex元件.ocx 你的安裝檔.inf 可能會用到的.dll abc.dll resources\*


    希望對你有幫助.

    回覆刪除
  3. 您好:

    想請教您 我想要在我的INF file內可以灌driver和執行exe file,需要如何處理?

    謝謝!

    回覆刪除
  4. Hi, 您好:

    想問您一個問題,如果我要用INF檔去執行exe檔,要使用那一種指令? 謝謝!

    Edward

    回覆刪除
  5. Jing先生您好
    我遇到一個問題是,當我的ocx改版,我要重新封裝cab檔時,INF檔是不是要加入甚麼才能順利將Client端的註冊檔及相關的Plugin一併更新呢?
    感謝您的指導

    EDDIE

    回覆刪除
  6. to eddie:

    我記得每一個 Section 都有一個 FileVersion 的tag, 你可以修改你的 inf
    裡面 FileVersion 的號碼.

    例如:
    [JingPlugin2.dll]
    file=thiscab ; 這個檔案從目前的 cab 檔解析出來
    FileVersion=0,0,0,0

    請參考: ActiveX 元件版本問題文章http://mqjing.blogspot.com/2009/03/plugin-activex.html

    另外, 如果你覺得每一個 Section 都要加版本號碼, 你可以使用變數
    請參考: INF 檔裡面可不可以使用變數?
    http://mqjing.blogspot.com/2009/03/plugin-inf.html

    希望對你有幫助.
    by Jing

    回覆刪除
  7. to eddie:

    我記得每一個 Section 都有一個 FileVersion 的tag, 你可以修改你的 inf
    裡面 FileVersion 的號碼.

    例如:
    [JingPlugin2.dll]
    file=thiscab ; 這個檔案從目前的 cab 檔解析出來
    FileVersion=0,0,0,0

    請參考: ActiveX 元件版本問題文章http://mqjing.blogspot.com/2009/03/plugin-activex.html

    另外, 如果你覺得每一個 Section 都要加版本號碼, 你可以使用變數
    請參考: INF 檔裡面可不可以使用變數?
    http://mqjing.blogspot.com/2009/03/plugin-inf.html

    希望對你有幫助.
    by Jing

    回覆刪除
  8. 想請問廠商只給我xxx.inf檔,這對使用者來說去安裝這個driver是很麻煩,因為硬體插入PC時,會跳出"尋找新增硬體精靈"視窗,還要從"從清單或特定位置安裝"去指到xxx.inf的路徑下,有沒有說可以製作像晶片金融卡讀卡機那樣的軟體,安裝完driver後,硬體就算是第一次插入也不會跳出"尋找新增硬體精靈"視窗,即可直接使用,請問這要怎麼去做到呢?

    回覆刪除
  9. 您好,偶然間看到你的文章,高手我想請問您一下如何可以將現有包好的cab檔另外包裝程執行檔,提供client端機器直接安裝,或者有更好的技術方法?感激不盡

    回覆刪除
  10. 你好, cab 是一種壓縮檔.
    我不知道有沒有其他的程式已經有這項功能.
    最笨的方法就是把 你的程式與 lzx 解壓縮程式 + 你的 cab 包成 exe 檔.

    然後傳給 client 整包.exe

    回覆刪除
  11. 大大這篇寫的真好,連我這個新手都很了解了,
    真是感謝喔! Very good!

    回覆刪除