取得winamp的NSIS教本的教程

來源:互聯網
上載者:User

建立 NSIS 指令碼的習慣: 建立一個 include 目錄,用來儲存安裝用的檔案, .nsi 檔案放在 include 的上級目錄,再在 include 目錄裡建立一個 resource,用來儲存一些資源檔比標、介面位元影像、自己修改的 UI 等等。

然後分析一下官方的安裝程式,嗯嗯,先清空臨時檔案夾,這是為了為了找東西方便,然後啟動安裝程式,再到臨時目錄裡找一個 nxxx.tmp 這樣的目錄,裡面有一些釋放出來的資源 gaydata.ini、modern-header.bmp、classic256.bmp、modern256.bmp、opt2page.ini、opt3page.ini。那幾個位元影像一看就明白,不用解釋,gaydata.ini 呢,裡面有從 sec0 到 sec47 的定義,所以我們可以確定一共有 47 個區段,而且區段的名稱是根據 gaydata.ini 來確定的,如何知道是根據 gaydata.ini 來確定的 的呢,你在安裝程式剛啟動的時候(剛顯示許可頁面的時候)找到臨時的那個目錄(也就是 NSIS 裡的 $PLUGINSDIR 目錄),把一個區段名稱改一下,比如把“Winamp (required)”改為 aaa,等進入組件選擇頁面的時候第一個就是 aaa 了,而如果把“Winamp (required)”清空的話,第一個區段就不見了。 opt2page.ini、opt3page.ini 分別是最後兩個頁面用來選擇串連方式和外觀的。分析後就可以動手了……

1.建立基本的結構

首先在指令碼頭部定義一些版本號碼等值,比如

!define VERSION "5.05"
!define VERSION_NUM "505"

這樣版本號碼變的時候在指令碼頭部改一下就行了,不用在指令碼的每個地方都改
然後定義輸出檔案名,為了方便 full、pro、lite 三個版本切換方便。

!define FILE_NAME "Winamp${VERSION_NUM}_full"

有關定義的說明可以看這裡

再下來就是安裝程式屬性的設定了,必須的設定有
Name "Winamp"
OutFile "${FILE_NAME}.exe"

當然

SetCompressor lzma

應該也是必須的,LZMA 不止壓縮率大很多,而且不太準確的一個屬性是啟動快不少,然後再設定一個區段就構成了主體部分,已經能夠編譯了

Section "主程式"
SectionEnd

2. 插入頁面

首先要

!include "MUI.nsh"

這樣才能使用 NSIS 提供的一些宏來插入頁面,要插入的頁面是

!insertmacro MUI_PAGE_LICENSE "./resource/License.txt"
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES

最後還要插入語言

!insertmacro MUI_LANGUAGE English

3. 完善安裝程式屬性設定
當然安裝程式的屬性還要增加一些設定

BrandingText "Nullsoft Install System -- built on ${__DATE__} at ${__TIME__}"

這是設定安裝程式個人標誌的

InstallDir "$PROGRAMFILES/Winamp"

設定一個預設的安裝路徑

InstallDirRegKey HKCU "Software/Winamp" ""

優先讀取註冊表裡儲存的路徑,如果存在就是用註冊表儲存的路徑

4. 設定頁面
表徵圖的定義

!define MUI_ICON "./resource/inst.ico"
!define MUI_UNICON "./resource/uninst.ico"

定義了安裝程式表徵圖和卸載程式表徵圖

!define MUI_HEADERIMAGE

定義在安裝程式頂端顯示一個位元影像

!define MUI_HEADERIMAGE_BITMAP "./resource/modern-header.bmp"

定義要顯示的位元影像,必須是本地機器上的

!define MUI_COMPONENTSPAGE_NODESC

指定組件選擇頁面不使用描述地區

5. 設定頁面文本

!define MUI_LICENSEPAGE_TEXT_TOP "Please read and agree to the license terms below before installing."

指定許可頁面上頂端顯示的文本

!define MUI_COMPONENTSPAGE_TEXT_TOP "This will install Winamp ${VERSION}. This installer contains the full install."

指定組件選擇頁面頂端的文本

!define MUI_DIRECTORYPAGE_TEXT_TOP "Setup has determined the optimal location to install. If you would like to change the folder, do so now."

指定目錄選擇頁面的文本

!define MUI_ABORTWARNING

定義按取消按鈕時,提示是否真的退出

6. 設定安裝類型,並把補全所有的區段

InstType "Full"
InstType "Standard"
InstType "Lite"
InstType "Minimal"

一共四個安裝類型,還有一個 Custom 類型系統會自動添加,不必幹預

然後在建立 46 個區段,一共有 47 個,名稱可以隨便起,因為區段的名稱到後面會由 gaydata.ini 來從命名,比如

Section " "
SectionEnd

7. .onInit 函數

這個函數是在安裝程式 GUI 啟動完畢的時候開始執行裡面的代碼,應該把那些資源檔在這個階段釋放到使用者電腦以供使用

InitPluginsDir

初始化 $PLUGINSDIR 也就是外掛程式目錄

File "/oname=$PLUGINSDIR/gaydata.ini" "./resource/gaydata.ini"
File "/oname=$PLUGINSDIR/opt2page.ini" "./resource/opt2page.ini"
File "/oname=$PLUGINSDIR/opt3page.ini" "./resource/opt3page.ini"
File "/oname=$PLUGINSDIR/classic256.bmp" "./resource/classic256.bmp"
File "/oname=$PLUGINSDIR/modern256.bmp" "./resource/modern256.bmp"

因為在 .onInit 裡使用 File 會使程式啟動時要搜尋很久,所以還應該使用 ReserveFile,ReserveFile 的說明看這裡。
在 !include "MUI.nsh" 上面增加

ReserveFile "./resource/gaydata.ini"
ReserveFile "./resource/opt2page.ini"
ReserveFile "./resource/opt3page.ini"
ReserveFile "./resource/classic256.bmp"
ReserveFile "./resource/modern256.bmp"
ReserveFile "${NSISDIR}/Plugins/InstallOptions.dll"

因為 InstallOptions.dll 在自訂介面要使用,所以也要加入

8. 組件的隱藏和顯示
細心的朋友都看到了指令碼裡面有兩個 !insertmacro MUI_PAGE_COMPONENTS,那麼組件選擇頁面就會出現兩次,察看 gaydata.ini 就知道第一次顯示的是 sec0 到 sec36,第二次顯示的是 sec37 到 sec 47。
關於頁面的說明請看這裡
每個頁面都有三個函數: Pre、Show、Leave,分別是預載入、顯示、離開,在 MUI 介面可以用定義的方法來插入函數,比如在 !insertmacro MUI_PAGE_COMPONENTS 前(插入上一個頁面之後) 定義一個 MUI_PAGE_CUSTOMFUNCTION_PRE 函數就可以插入一個預載入函數。在本次指令碼中在第一個組件選擇頁面作如下定義

!define MUI_PAGE_CUSTOMFUNCTION_PRE ComponentPre
!define MUI_PAGE_CUSTOMFUNCTION_SHOW ComponentShow

上面定義了 ComponentPre、ComponentShow 函數,當然定義的函數名可以隨便起,但一般來說名字都要表達它的含義,便於閱讀。

在開始建立這兩個函數之前還要定義一些內容

!define SECTION_COMPONENT_END 36
!define SECTION_ASSCOIATION_START 37
!define SECTION_TOTAL 47

上面定義了 36 是要安裝的組件最後的區段索引好,37 是檔案關聯等的開始區段索引號,47 是總共的區段數。ComponentPre 函數的內容如下

Function ComponentPre
Push $0
Push $1

Call SectionTextReset

StrCpy $1 0
loop:
ReadINIStr $0 "$PLUGINSDIR/gaydata.ini" "secnames" "sec$1"
StrCmp $0 "" 0 +2
SectionSetText $1 ""
StrCmp $1 ${SECTION_COMPONENT_END} loop_quit
IntOp $1 $1 + 1
Goto loop
loop_quit:

StrCpy $1 ${SECTION_ASSCOIATION_START}
SectionSetText $1 ""
StrCmp $1 ${SECTION_TOTAL} +3
IntOp $1 $1 + 1
Goto -3

Pop $1
Pop $0
FunctionEnd

這個函數調用了 SectionTextReset 函數,SectionTextReset 函數如下

Function SectionTextReset
Push $R0

StrCpy $R0 0
SectionSetText $R0 " "
StrCmp $R0 ${SECTION_TOTAL} +3
IntOp $R0 $R0 + 1
Goto -3

Pop $R0
FunctionEnd

SectionTextReset 函數構成一個迴圈,$R0 從 0 開始遞增,直到等於 ${SECTION_TOTAL} 後跳出迴圈,這個迴圈把所有區段的名稱都重設為空白格,在兩個 MUI_PAGE_COMPONENTS 頁面的預載入函數都調用一次。這是因為 Show 函數會把一些區段隱藏,即把區段名稱設為空白值,在下一個 MUI_PAGE_COMPONENTS 頁面的 Pre 階段必須給它一個名稱,否則它將一直隱藏。

調用了 SectionTextReset 函數之後是一個迴圈,這個迴圈讀取 "$PLUGINSDIR/gaydata.ini" 的 sec0 到 ${SECTION_COMPONENT_END} ,如果某個 sec 讀到的值為空白,則把該區段隱藏,也就是把區段名設為空白值。你可以試試英文原版,剛啟動時把 "$PLUGINSDIR/gaydata.ini" 的 sec0 設為空白值,到了組件選擇頁面 Winamp (required) 區段就被隱藏了。

再下來也是一個迴圈,把 ${SECTION_ASSCOIATION_START} 到 ${SECTION_TOTAL} 的區段隱藏,因為第一個 MUI_PAGE_COMPONENTS 只需要顯示 0 到 ${SECTION_COMPONENT_END} 的區段。ComponentShow 函數如下

Function ComponentShow
Push $0
Push $1

StrCpy $1 0
loop:
ReadINIStr $0 "$PLUGINSDIR/gaydata.ini" "secnames" "sec$1"
SectionSetText $1 $0
StrCmp $1 ${SECTION_COMPONENT_END} loop_quit
IntOp $1 $1 + 1
Goto loop
loop_quit:

Pop $1
Pop $0
FunctionEnd

也是一個迴圈,$1 的值從 0 到 ${SECTION_COMPONENT_END} 遞增,則是依次從 sec0 到 sec36 讀取 gaydata.ini 相應的值,並根據讀取道的值來從命名區段名稱。

第二個組件頁面對應的 AsscoiationPre、AsscoiationShow 與上面的基本一致,只是要隱藏的區段索引不同而已。

9. 隱藏控制項
組件頁面第二次顯示的時候,有幾個控制項是隱藏的,用 Resource Hacker 開啟 ${NSISDIR}/Contrib/UIs/modern.exe 裡面的 104 對話方塊就是組件顯示頁面,要隱藏的空間 ID 為 1017 (顯示安裝類型) 和 1021 (它左邊顯示的文本) 還有 1023 (磁碟空間顯示的控制項)。顯示和隱藏控制項的指令為 ShowWindow ,說明請看這裡。
隱藏控制項的代碼需要加在 AsscoiationShow 函數裡。

FindWindow $0 "#32770" "" $HWNDPARENT

擷取一個視窗控制代碼儲存在 $0 裡

GetDlgItem $1 $0 1017

擷取 1017 控制項的控制代碼

ShowWindow $1 ${SW_HIDE}

隱藏 1017 控制項,其他幾個控制項的隱藏指令依次為

GetDlgItem $1 $0 1021
ShowWindow $1 ${SW_HIDE}
GetDlgItem $1 $0 1023
ShowWindow $1 ${SW_HIDE}

除了控制項隱藏之外,還有兩處文本需要更改,由於使用 !define 只能對第一次顯示的組件頁面更改,所以第二次顯示的文本只能自己用 SendMessage 來改了

GetDlgItem $1 $0 1006
SendMessage $1 ${WM_SETTEXT} 0 "STR:Select which icons you want installed, and whether you want files and CDs associated with"
GetDlgItem $1 $0 1022
SendMessage $1 ${WM_SETTEXT} 0 "STR:Select icons to install and media associations:"

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.