nsis 确實是一個不錯的安裝程式制作軟體。新版本 2.0a7 真正實作了中文支援和支援 winxp 的安裝對話框。
不過要用它實作漂亮的安裝界面和完美的安裝功能就必須好好的寫腳本。 而 nsis 的腳本指令是在是太多了,有時候覺得好像又回到了學習 c
語言的年代。他豐富而起強大的功能甚至 可以編譯出一些小而使用的軟體(例如查找視窗句柄,然後...) 好了,不多說。我在這裡着重介紹關于 nsis
的一些使用問題以及新界面安裝程式的制作過程,中間會附上一個 示例腳本。 這裡隻說單語言的簡體中文 1. nsis的運作問題 2.0a7 的 nsis
安裝在長檔案名的目錄中好像會有問題(win2k 和 winxp 下,win98 下好像沒問題)。你若是将 nsis
安裝在類似于“e:/system/installer/nsis 的目錄中”(其中的“installer”是超過了 8 個字元的長文 件名),運作
makensisw 或是直接在指令提示符中使用 makensis 可能會非法操作。 解決的辦法是:在指令提示符下使用如下指令: cd
e:/system/instal~1/nsis 進入 nsis 安裝目錄後使用指令行: makensis /cd /x"compressor bzip2"
"f:/1.nsi" 你可以在腳本檔案中使用了“setcompressor bzip2”指令,這樣就可以去掉“/x"compressor bzip2"”參數。
使用 makensisw 的朋友我就不多說了,你可以從我上面的分析中得到點啟發。自己設定一下它的運作參數吧! 不過 makensisw 也有 bug,若用
makensisw 編譯時發現腳本錯誤,程式就立馬非法操作。 2. 關于腳本的整體布局 說 nsis 有些象進階語言的文法一點沒錯。nsis
的文法非常注重先後順序(我曾經為了一個指令的先後順序來 回 ctrl+c & ctrl+v 了 n 次)。
例如象它的幫助檔案中提到的“setfont”指令必須在“addbrandingimage”指令之前等。我在這裡要說的而是
關于如何正确的對腳本進行整體布局,使其能更加合理、高效的被使用,這樣才有利于日後的安裝程式更新 你可以用我後面的示例腳本為模闆制作自己的 nsis 腳本。
大體布局如下: //////////////////////////////////////////////////////////////
預設參數(包括外部壓縮器選擇、編譯選項、宏定義以及檔案包含等) 普通安裝設定 自定義函數 安裝程式區域内容 安裝程式回調函數及其相關函數定義 解除安裝程式區域内容
解除安裝程式回調函數及其相關函數定義 //////////////////////////////////////////////////////////////
3. 關于安裝程式 logo 畫面的說明: 先前版本的 nsis 使用 splash.exe 制作 logo畫面,但若您使用 2.0a7,
我建議您使用(好像也隻能使用)magiclime.exe,它在 win2k 和 winxp 下顯示 logo畫面時會有淡入淡出的效果。超 cool.... 4.
關于标牌位圖(即顯示在安裝程式對話框中的自定義位圖)的說明: 2.0a7 提供了宏指令用于在安裝程式的對話框中顯示标牌位圖。當然你也可以用标準的 nsis
指令。 5. 關于使用新的 modern ui 界面的說明: 2.0a7 同樣提供了宏指令使你可以使用全新的安裝界面: 首先你需要安裝 nsis v2.0a7
簡體中文更新檔(漢化新世紀有下載下傳): 然後打開安裝目錄下的 examples/modern ui/modernui.nsh 檔案,将從 !macro
mui_interface ui icon unicon checks progressbar 到第一個 !macroend
之間的注釋符(即分号)删除(若沒有這步究省了)。儲存。 接下來就可以在你自己的腳本中使用形式對話框了,并且支援 winxp 的新的視覺效果樣式。 6.
以下是我的示例腳本:
////////////////////////////////////////////////////////////////////////////
; study.nsi ; ; 以下腳本用以生成 study.exe 檔案 ; 它包含有授權協定 ; ;
安裝時若發現應用程式正在運作,安裝程式會提示并替使用者關閉應用程式 ; 安裝成功後會自動運作應用程式 ; ; 啟用新的 modern ui
的宏指令文法,原先的部分指令将被禁止以防止重複 ; 我會盡量展示如何基本指令的用法。當然宏指令也會與一些基本指令發生重 ; 複定義的情況,不過 nsis
照樣能編譯成功. ; 其中的一些路徑、檔案你可以根據需要更改
; 啟用外部壓縮工具(這裡我們不用,原因看第 10 步) ;!define
have_upx
; 若啟用了外部壓縮工具,這進行可執行檔案頭的壓縮 !ifdef have_upx ; 用 upx
壓縮可執行檔案頭(用其他的相關工具也行) !packhdr tmp.dat "e:upx/upx --best tmp.dat" !endif
;
編譯選項 ; 設定覆寫标記 setoverwrite on ; 設定壓縮選項 setcompress auto ; 選擇壓縮方式 setcompressor
bzip2 ; 設定資料塊優化 setdatablockoptimize on ; 設定資料寫入時間 setdatesave on
; 相關資料預設
; 軟體的名字,後面的${name}調用這個名字 !define name "nsis" !define name_full "全方位掌握 nsis 的使用"
!verbose 3 ; 包含視窗消息定義檔案 !include "${nsisdir}/examples/winmessages.nsh" ;
包含新界面的宏指令檔案 !include "${nsisdir}/examples/modern ui/modernui.nsh" ; 包含标牌位圖宏指令檔案
!include "${nsisdir}/examples/branding.nsh" !verbose 4 !define currentpage $9
!define temp1 $r0 !define temp2 $r1 ; 插入安裝界面宏定義(這裡我禁用了,啟用也沒問題。編譯照樣通過。後面我都定義過了)
;!insertmacro mui_interface "modern2.exe" "adni18-installer-c-no48xp.ico"
"adni18-uninstall-c-no48xp.ico" "modern.bmp" "smooth"
; 安裝程式設定 ; 輸出檔案
outfile "f:/study.exe" ; 安裝程式名稱 name /lang=2052 "nsis" ; 替換對話框樣式 changeui all
"${nsisdir}/contrib/uis/modern2.exe" ; 啟用 windowsxp 的視覺樣式 xpstyle on ;設定字型
setfont 宋體 9 ; 标題名稱 caption /lang=2052 "全方位掌握 nsis 的使用" ; 标牌的内容 brandingtext
/lang=2052 /trimcenter "shao hao" ; 安裝程式圖示 icon "f:/12/qcdicon.ico" ; 安裝程式顯示标題
windowicon on ; 添加标牌位圖(放在頂部用 top 參數。後面接高度) addbrandingimage left 105 ;
設定漸變背景 bggradient off ; 設定安靜安裝模式 ;silentinstall normal ; 設定安靜解除安裝模式
;silentuninstall normal ; 執行 crc 檢查(最好用 on 打開。關閉是因為還要修改安裝程式,看第 10 步) crccheck
off ; 加載相應的語言檔案 loadlanguagefile "${nsisdir}/contrib/language
files/simpchinese.nlf" ; 替換各個對話框标題的文字 subcaption /lang=2052 0 "授權協定" subcaption
/lang=2052 1 "安裝選項" subcaption /lang=2052 2 "安裝目錄" subcaption /lang=2052 3
"正在安裝" subcaption /lang=2052 4 "完成安裝" ; 替換預設按鈕的文字 miscbuttontext /lang=2052
"< 上一步" "下一步 >" "取消" "關閉" ; 替換“安裝”按鈕的文字 ;installbuttontext /lang=2052
"安裝" ; 替換當檔案無法被寫入時的警告窗的文字 fileerrortext /lang=2052
"無法寫入檔案$/r$/n$0$/r$/n請确認檔案屬性不是隻讀且未被使用中!" ; 預設的安裝目錄 installdir
"$programfiles/qcd 3" ; 如果可能的化從系統資料庫中監測安裝路徑 installdirregkey hklm /
"software/microsoft/windows/currentversion/uninstall/nsis" /
"uninstallstring" ;
授權協定頁面 licensetext /lang=2052 "nsis 是免費軟體。安裝前請先閱讀以下協定條款" "我同意" ; 使用授權協定文本
licensedata /lang=2052 "f:/12/license.txt" ; 設定授權協定頁面的背景色 ;licensebkcolor
000000 ; 選擇要按安裝的元件 componenttext /lang=2052 "現在将安裝 ${name_full}到您的計算機:"
"請選擇安裝類型" "或選擇您希望安裝的元件" insttype "完全安裝(都在了)" insttype "典型安裝" insttype
/lang=2052 /customstring=自定義 ;insttype /lang=2052 /nocustom ;insttype
/componentsonlyoncustom checkbitmap "${nsisdir}/contrib/icons/modern.bmp" ;
替換顯示磁盤空間資訊的文字 spacetexts /lang=2052 "所需空間:" "可用空間:" ; 提示使用者輸入目錄的文本 ; dirshow
hide ; 替換顯示選擇安裝目錄的文字 dirtext /lang=2052 "請選擇 ${name} 的安裝路徑:" "選擇目錄用以安裝
${name}:" "浏覽..." ; 是否允許安裝在根目錄下 allowrootdirinstall false ; 安裝資訊的顔色
;installcolors 000000 ffffff ; 安裝進度條顯示方式 instprogressflags smooth colored ;
完成後自動關閉安裝程式 autoclosewindow true ; 顯示“顯示詳細細節”對話框 showinstdetails hide ;
替換“顯示細節”按鈕的文字 detailsbuttontext /lang=2052 "顯示細節" ; 替換“完成”按鈕的文字 completedtext
/lang=2052 "已完成"
; 解除安裝程式設定 ; 替換解除安裝程式的文字 uninstalltext /lang=2052 "現在将從你的系統中解除安裝
${name}:" "解除安裝目錄:" ; 解除安裝程式圖示 uninstallicon "f:/12/unqcdicon.ico" ; 替換解除安裝程式标題的文字
uninstallcaption /lang=2052 "解除安裝 ${name}" ; 替換解除安裝程式每頁按鈕的文字 uninstallsubcaption
/lang=2052 0 ":确認" uninstallsubcaption /lang=2052 1 ":正在删除檔案"
uninstallsubcaption /lang=2052 2 ":完成" ; 解除安裝程式顯示方式 showuninstdetails hide ;
替換“解除安裝”按鈕的文字 uninstallbuttontext /lang=2052 "解除安裝"
; 安裝程式内容及其相關的回調函數 ; 安裝程式内容
section /e "!主要程式(必須安裝)" seccore sectionin 1 2 ro ; 設定輸出路徑,每次使用都會改變
setoutpath $instdir ; 循環包含目錄下全部内容 file /r "f:/12/1/*.*" ; 隻包含一個檔案 file
"f:/12/gf.gif" ; 處理動态連接配接庫檔案 iffileexists "$instdir/1.dll" 0 nofile1 ; 取消元件注冊
unregdll "$instdir/1.dll" delete "$instdir/1.dll" nofile1: file "f:/12/1.dll"
; 注冊元件 regdll "$instdir/qcdiconmgr.dll" ; 寫入軟體注冊鍵值 writeregstr hklm
"software/nsis/nsis" "" "$instdir" ; 為 windows 解除安裝程式寫入鍵值 writeregstr hklm
"software/microsoft/windows/currentversion/uninstall/nsis" "displayname"
"nsis(隻用于移除)" writeregstr hklm
"software/microsoft/windows/currentversion/uninstall/nsis" "uninstallstring"
"$instdir/uninst.exe" ; 寫入生成解除安裝程式(可多次使用) writeuninstaller "$instdir/uninst.exe"
sectionend section /e "擴充(可選)" secupdate sectionin 1 setoutpath
"$instdir/plugins" file "f:/12/qcdplus/plugins/2.dll" file /r
"f:/12/qcdplus/plugins/3" sectionend subsection /e "選項" secoptions section /e
"建立桌面圖示" secdesktopshortcut sectionin 1 2 setoutpath
"$instdir/plugins" createshortcut "$desktop/nsis.lnk"
"$instdir/gf.gif" writeuninstaller "$instdir/uninst.exe"
sectionend section /e "建立快速啟動欄圖示" secquickbarshortcut sectionin 1
2 setoutpath "$instdir/plugins" createshortcut
"$quicklaunch/nsis.lnk" "$instdir/gf.gif" writeuninstaller
"$instdir/uninst.exe" sectionend section /e "建立 nsis 程式組" secshortcutgroup
sectionin 1 2 setoutpath "$instdir/plugins"
createdirectory "$smprograms/nsis" createshortcut "$smprograms/qcd
player/gf.lnk" "$instdir/gf.gif" writeuninstaller
"$instdir/uninst.exe" sectionend subsectionend section "-run"; 運作 execwait
"$instdir/2.exe" -p writeinistr "$instdir/nsis.ini" "2" "language" "chinese"
exec "$instdir/2.exe" execshell open "$instdir/漢化說明.htm" sectionend section ""
;invisible section to display the finish header !insertmacro mui_finishheader
setheader sectionend
; 安裝程式初始化設定 function .oninit ; 發現有程式正在運作時提示退出後繼續運作
loop: findwindow $r0 "nsis" intcmp $r0 0 done messagebox
mb_okcancel /
"nsis 正在運作。$/n點選“确定”按鈕會關閉 nsis 然後繼續安裝,點選“取消”按鈕将退出安裝程式" /
idok noabort abort noabort: sendmessage $r0 1029 0 0 ;
稍等後繼續檢測直至檢測不到或使用者選擇取消 sleep 444 goto loop done: ; 顯示 logo
畫面 setoutpath $temp
file /oname=qcd_logo.bmp "f:/12/logo.bmp" file
/oname=magiclime.exe "${nsisdir}/bin/magiclime.exe" execwait
"$temp/magiclime.exe" qcd_logo.bmp delete "$temp/magiclime.exe" delete
"$temp/qcd_logo.bmp" ; 初始化标牌位圖 !insertmacro bi_init $r0 functionend ;
安裝程式主界面的相關文本 function setheader !insertmacro mui_header_init
!insertmacro mui_header_start 1 !insertmacro
mui_header_text 2052 "授權協定" "安裝 ${name} 之前,請認真閱讀一下授權條款."
!insertmacro mui_header_stop 1 !insertmacro mui_header_start 2
!insertmacro mui_header_text 2052 "選擇元件" "請選擇你要安裝的元件."
!insertmacro mui_header_stop 2 !insertmacro
mui_header_start 3 !insertmacro mui_header_text 2052
"選擇安裝位置" "為 ${name} 選擇一個安裝目錄." !insertmacro mui_header_stop 3
!insertmacro mui_header_start 4 !insertmacro
mui_header_text 2052 "安裝" "${name} 已經安裝,請等待." !insertmacro
mui_header_stop 4 !insertmacro mui_header_start 5
!insertmacro mui_header_text 2052 "完成" "安裝順利完成."
!insertmacro mui_header_stop 5 !insertmacro mui_header_end functionend ;
初始化安裝程式對話框的顯示文本 function .oninitdialog !insertmacro mui_innerdialog_init
!insertmacro mui_innerdialog_start 1
!insertmacro mui_innerdialog_text 2052 1040
"如果你同意協定中的所有條款,選擇“我同樣”繼續安裝,如果你選擇了“取消”,安裝程式将終止,隻有接受條款才能安裝 ${name}."
!insertmacro mui_innerdialog_stop 1 !insertmacro
mui_innerdialog_start 2 !insertmacro
mui_innerdialog_text 2052 1042 "描述" !insertmacro
mui_innerdialog_text 2052 1043 "移動你的滑鼠到元件上,便可以見到相關的描述."
!insertmacro mui_innerdialog_stop 2 !insertmacro
mui_innerdialog_start 3 !insertmacro mui_innerdialog_text
2052 1041 "目标檔案夾" !insertmacro mui_innerdialog_stop 3
!insertmacro mui_innerdialog_end functionend ; 轉到下頁面時的處理 function .onnextpage
!insertmacro mui_nextpage_outer !insertmacro mui_nextpage setheader ;
标牌位圖設定 !insertmacro bi_next functionend ; 轉到上一頁面時的處理 function .onprevpage
!insertmacro mui_prevpage ; 标牌位圖設定 !insertmacro bi_prev functionend ;
滑鼠移到指定元件時的顯示處理 function .&#111nmouseoversection ; 用宏指令設定安裝自己的注釋文本 !insertmacro
mui_description_init !insertmacro mui_description_text 2052
${seccore} "安裝主應用程式" !insertmacro mui_description_text 2052
${secupdate} "安裝 nsis 的更新或新增插件" !insertmacro mui_description_text
2052 ${secoptions} "選擇 nsis 的其他安裝選項,例如:建立快捷方式和應用程式組的" !insertmacro
mui_description_text 2052 ${secdesktopshortcut} "在使用者的桌面上建立 nsis 的快捷方式"
!insertmacro mui_description_text 2052 ${secquickbarshortcut}
"在使用者的快速欄裡建立 nsis 快捷方式" !insertmacro mui_description_text 2052
${secshortcutgroup} "在使用者的開始菜單的程式中建立 nsis 的快捷方式組" !insertmacro
mui_description_end functionend ; 安裝成功完成後的設定 function .oninstsuccess ; 自己加吧:)
functionend ; 放棄安裝時警告視窗的顯示資訊 function .onuserabort !insertmacro
mui_abortwarning 2052 "你确定要推出 ${name} 的安裝嗎?" !insertmacro mui_abortwarning_end
functionend ; 安裝程式标牌位圖清單 !insertmacro bi_list !insertmacro bi_list_add
"f:/12/brand1.bmp" /resizetofit !insertmacro bi_list_add "f:/12/brand2.bmp"
/resizetofit !insertmacro bi_list_add "f:/12/brand3.bmp" /resizetofit
!insertmacro bi_list_end
; 解除安裝程式及其相關回調函數 ; 解除安裝程式内容 section "uninstall"
execwait "$instdir/12.exe" /un ; 循環删除檔案直至删除檔案夾 rmdir /r "$smprograms/nsis"
unregdll "$instdir/2.dll" delete "$instdir/qcdiconmgr.dll" delete
"$instdir/*.*" deleteregkey hklm "software/nsis" deleteregkey hklm
"software/microsoft/windows/currentversion/uninstall/nsis" messagebox
mb_yesno|mb_iconquestion /
"是否連插件目錄也要删除?$/n(若您要保留這些檔案,請點選下面的“否”按鈕)" /
idno nodelete
; 全删光!!! rmdir /r "$instdir" nodelete: sectionend
; 定義解除安裝程式标牌位圖 !define
bi_uninstall !include "${nsisdir}/examples/branding.nsh" ; 初始化解除安裝程式對話框的設定
function un.oninit ; 初始化标牌位圖 !insertmacro bi_init $r0 functionend ;
解除安裝程式主界面的相關文本 function un.setheader !insertmacro mui_header_init
!insertmacro mui_header_start 1 !insertmacro
mui_header_text 2052 "解除安裝 ${name}" "${name_full} 将從你的系統裡移除."
!insertmacro mui_header_stop 1 !insertmacro mui_header_start 2
!insertmacro mui_header_text 2052 "解除安裝" "${name}
正在被解除安裝,請等待." !insertmacro mui_header_stop 2
!insertmacro mui_header_start 3 !insertmacro
mui_header_text 2052 "完成" "${name_full} 已從你的系統中移除." !insertmacro
mui_header_stop 3 !insertmacro mui_header_end functionend ; 初始化解除安裝程式對話框時的處理
function un.oninitdialog ; 自己加:) functionend ; 解除安裝程式轉到下一頁時的處理 function
un.onnextpage !insertmacro mui_nextpage_outer !insertmacro mui_nextpage
un.setheader ; 标牌位圖設定 !insertmacro bi_next functionend ; 解除安裝程式完成時的處理 function
un.onuninstsuccess ; 再加^_^ functionend ; 放棄解除安裝程式時的處理 function un.onuserabort
functionend ; 解除安裝程式标牌位圖清單 !insertmacro bi_list !insertmacro bi_list_add
"f:/12/unbrand1.bmp" /resizetofit !insertmacro bi_list_add "f:/12/unbrand2.bmp"
/resizetofit !insertmacro bi_list_end
; 結束
/////////////////////////////////////////////////////////////////////////////
7.注意兩個标牌位圖清單宏指令必須放置到函數的後面,就像我編寫的那樣,安裝程式的标牌位
圖清單放置到到所有安裝程式回調函數的後面;解除安裝程式的标牌位圖清單放置到所有解除安裝程式回 調函數的後面。
關鍵是要注意整體布局(這樣才不會看迷糊),當然若編譯不能通過,就要進行合适的調整。 8. 使用指令: makensis /cd f:/study.nsi"
進行編譯(這個示例腳本我沒試過-_-,若編譯無法通過隻好自己動手研究研究了。我放出來隻是用于參考學習) 9. 還沒完—— nsis
對多語言的支援還是不夠完美(注意:是完美——有點雞蛋裡挑骨頭的味道)。 我們繼續: 用 exescope (其他的資源編輯器也行,别說你沒有)打開生成的
study.exe 檔案,找到對話框資源的 105 項 目。你會發現有一塊很明顯的用以顯示标牌位圖的控件。因為 nsis
在插件此控件時是使其保持于授權協定檔案 控件等高的,是以當使用用 modern2.exe 對話框模闆時會與對話框頂部多出 45 的距離——不羅嗦了,總之根據
需要搞得好看就行(别過火!)。 順便提一下,nsis 安裝目中的 contrib/uis 子目錄下提供了多種對話框模闆,你可以自行選用(就是用
changeui 指令或用宏指令),甚至根據需要用資源編輯器修改模闆資源。 接着修改:找到 111
項,把裡面的資源漢化掉(新的界面居然沒有對此對話框的多語言支援!這個對話框隻有在 大容量的安裝程式執行時才顯示)。 用 exescope 更新後,再用 hex
workshop 打開我問可憐的試驗品——study.exe,查找字元串 “unpacking data: ”(沒引号的,你别瞎加。找不到别怪我
$_$)。找到後處理一下,用“正在解壓縮資料:” 替換(正好 8 個字元 yeah!)。 10. 現在我要說為什麼不啟用 upx 壓縮以及關閉 crc 檢測:
用 upx 壓縮可執行檔案頭或啟用 crc 檢測(起用的話就是打開了自校驗),我們的 exescope
就無用武之地了。但關于crc校驗又有些特别:使用者可以在指令行提示符下使用 /ncrc
開關參數執行安裝程式,例如:若安裝程式得檔案名為“setup.exe”,那麼就在指令行提示符下鍵入“setup.exe /ncrc”就可跳過 crc
校驗執行安裝程式(但如果你将crccheck指令的參數設定為force的話,就什麼辦法也沒了),但這樣對使用者而言比較麻煩。
至此全部完工。
若有任何文法難點,請參閱 nsis
的幫助檔案(有了中文版的應該友善些吧!)。内有上千字的詳細說明(可能更多,我也沒統計過)。還有一些指令我沒有用上,因為那些不太可能用的上。
這個示例腳本已能作出較佳的安裝程式界面,大家看看我為 qcd v3.40b35 做的安裝界面。
編譯腳本非法操作的問題我也見識過了~!我也有個偏方~!在編譯時按住該運作視窗不放,直到運作結束(有時會不顯示運作狀态,自行判斷時間吧),這個方法屢試不爽~!:)
2.0a7依然支援splash.exe 編寫啟動logo哦~! 指令如下:
function .oninit setoutpath $temp file /oname=spltmp.bmp "f:/my
documents/hanzify1.bmp" ; optional ; file /oname=spltmp.wav
"my_splashshit.wav" file /oname=spltmp.exe "${nsisdir}/bin/splash.exe"
execwait "$temp/spltmp.exe" 1000 $hwndparent $temp/spltmp delete
$temp/spltmp.exe delete $temp/spltmp.bmp ; delete $temp/spltmp.wav
functionend
另外,我建議把簡體中文語言包和一些常用宏指令檔案裡的語言設定改為2052,就可以在編腳本時偷懶一點啦~!同時顯示效果也要好一些