問: 在安裝過程中按“取消”的話,會彈出是否終止安裝的確認視窗,請問怎樣設定可以讓這個視窗不要出現,按“取消”就直接退出呢?
答: !define MUI_ABORTWARNING 把這句去掉就可以了....
問: 的地方,現在顯示的是“setup 將安裝...”,除了用自訂字串來修改這個地方以外,如何把這個setup搞成其他的?比如“安裝程式現在將...”
答: DirText "安裝程式將安裝 $(^NameDA) 在下列檔案夾。要安裝到不同檔案夾,單擊 [瀏覽(B)] 並選擇其他的檔案夾。 $_CLICK"
附圖:
問: 如何定義歡迎頁面的標題字型大小。如所示,圖三紅色框內的標題字型。
答: 使用以下指令碼
!define MUI_PAGE_CUSTOMFUNCTION_SHOW ChageFONT
!insertmacro MUI_PAGE_WELCOME
Function ChageFONT
GetDlgItem $0 $MUI_HWND 1201
createFont $1 "Tahoma" "11" "700"
SendMessage $0 ${WM_SETFONT} $1 0
FunctionEnd
附圖:
問: 添加版本號碼
VIProductVersion "1.2.3.4"
VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "Test Application"
VIAddVersionKey /LANG=${LANG_ENGLISH} "Comments" "A test comment"
VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "Fake company"
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalTrademarks" "Test Application is a trademark of Fake company"
VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "?Fake company"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "Test Application"
VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "1.2.3"
在指令碼中加入上面的代碼,則為 NSIS 產生的 exe 添加版本資訊。
問題就是,能否讓屬性中語言顯示為“中文(中國)”?如附圖1
答: 中文 ID 是 2052。 把 ${LANG_ENGLISH} 改為 2052。
問: 用 2052 之後確實變成“中文(中國)”了。但其他內容仍舊是亂碼,不知有什麼辦法可以解決嗎?如附圖2
答: 版本資訊設定語句,放在 !insertmacro MUI_LANGUAGE 的後面,NSIS 要注重次序的。如果使用古典介面,放在 LoadLanguageFile "${NSISDIR}/Contrib/Language files/SimpChinese.nlf" 的後面。
附圖:
問: 如何禁止顯示如附圖中的 banner 。
答: 圖示的效果是因為安裝程式初始化的時候,也就是 .onInit 函數裡需要用到某個檔案的時候安裝程式需要搜尋整個資料區塊來把它解壓出來,當安裝程式比較大的時候搜尋比較費時,這個時候才顯示解壓百分比。一般都是用 ReserveFile 來避開這種搜尋。
比如 Function .onInit 裡有
InitPluginsDir
File "/oname=$PLUGINSDIR/io.ini" "./io.ini"
或者其他類似的話,安裝程式就需要搜尋並解壓這個檔案
一般在指令碼頭部加
ReserveFile "./io.ini"
這樣 io.ini 就儲存在資料區塊的尾部,安裝程式初始化的時候就不用搜尋整個資料區塊了,相當於加快了安裝程式的啟動速度。
問: 根據以上方法使用了,確實不會再出現初始化的對話方塊了,但是在自訂的 InstallOptions 頁顯示前,程式還是會停頓一段時間,請問這是為何?如何避免?
答: 某些控制項比較消耗時間的,比如顯示 ICON、位元影像 等,如果 InstallOptions 裡含有這些控制項可能會停頓。如果 InstallOptions 是第一個頁面的話還要把 InstallOptions.dll 加入到 ReserveFile 參數裡。再或者就是進入 InstallOptions 的時候含有比較複雜的指令,比如迴圈等。
一般在加入 ReserveFile ${NSISDIR}/Plugins/InstallOptions.dll 既可避免。
附圖:
問: 如何運行一個安裝檔案 .inf
答: ExecWait "RunDll32 advpack.dll,LaunchINFSection skins.inf,DefaultInstall"
問: 關聯檔案表徵圖後,表徵圖沒變化。
答: 重新整理表徵圖用, System::Call shell32.dll::SHChangeNotify(l, l, i, i) v (0x08000000, 0, 0, 0)
問: 我用NSIS做好了一個安裝程式,因為資料較多,一共有400多M,用的LZMA壓縮方式,做好後的安裝程式約200M,但是我發現在運行這個安裝程式時會在系統TEMP目錄產生一個同安裝後的全部內容同樣大的臨時檔案(一邊運行一邊加大,最後到400多M去了),如果我做的程式小倒沒什麼,可是這個程式有400多M,除了要寫入安裝的資料外還要同樣大小的空間放臨時檔案,這樣子也實在是太花不來,
我想請問:有什麼辦法能讓其在安裝時不使用這麼多的臨時空間嗎?安裝的指令碼是用HM NIS Edit的嚮導產生的。
答: 這是因為 NSIS 在用 LZMA 時採用了固實壓縮,何謂固實壓縮,其實就是把所有檔案統一起來壓縮,所以這樣壓出來的檔案更加的小,同時也帶來了一個問題,安裝解壓的時候,在臨時檔案夾中產生一個臨時檔案,隨著安裝的進程逐漸增大,到最後,需要臨時檔案會變成跟原安裝程式一樣大,也就是說,需要原安裝程式 2 倍的空間才可以安裝這個程式,所以對於安裝大量檔案時,這是不適合的。
NSIS 2.07 版本之前 LZMA 演算法是固實壓縮的,沒有非固實的選項,如果需要這樣做,只有下載非固實壓縮的編譯器,但是 2.07 後的 NSIS 的 LZMA 壓縮已經改為預設非固實壓縮了,所以這個問題同時也不再存在。如果在製作少量檔案的安裝時,仍然想取用固實壓縮可以加入 /SOLID 參數。像這樣: SetCompressor /SOLID lzma
問: 能不能在 Section 區段中實現讀取INI檔案狀態來安裝。
,若選中單選框1則安裝1中定義的檔案。若不選中則不安裝。若選中單選框2則安裝2定義的檔案。若不選則不安裝。
答: 使用以下代碼,
!include LogicLib.nsh
Section -post
SetOutPath $INSTDIR
!insertmacro MUI_INSTALLOPTIONS_READ $INI_VALUE "info.ini" "Field 2" "State"
${If} $INI_VALUE = 1
File /a "./file/fileA.exe"
File /a "./file/fileB.exe"
${EndIf}
!insertmacro MUI_INSTALLOPTIONS_READ $INI_VALUE "info.ini" "Field 3" "State"
${If} $INI_VALUE = 1
File /a "./file/fileA.exe"
${EndIf}
SectionEnd
或者使用以下代碼,
!include LogicLib.nsh
Section -post
SetOutPath $INSTDIR
!insertmacro MUI_INSTALLOPTIONS_READ $INI_VALUE "info.ini" "Field 2" "State"
${If} $INI_VALUE = 1
;選中時執行的代碼
File /a "./file/fileA.exe"
File /a "./file/fileB.exe"
${Else}
;不選中時執行的代碼
File /a "./file/fileA.exe"
${EndIf}
SectionEnd
附圖:
問: 在 NSIS 中如何設定工作目錄,例如一些檔案的捷徑,還有安裝完一個軟體後運行一個程式,而這個程式需要檢測當前工作目錄下的某個檔案,這時候設定工作目錄尤為重要,否則程式不能正常運行。
答: NSIS 中設定工作目錄使用 SetOutPath,例如在運行程式的代碼 ExecWait "$INSTDIR/test2.exe" 前放入 SetOutPath $INSTDIR,那麼 $INSTDIR 將會成為當前的工作目錄,建立捷徑也會把工作目錄設為 $INSTDIR。
卸載之前運行某程式只需要把運行指令放到 Function un.onInit 裡就行
問: 記得以前看到有文章介紹過可在NSIS中調用.inf檔案安裝附加驅動程式,具體實現代碼如下形式:
ExecWait "RunDll32 advpack.dll,LaunchINFSection drivers.inf,DefaultInstall"
偶在打包一小東東時使用了這一方法,但遇到的問題時,如果在卸載區段裡設定能自動卸載安裝過的驅動程式呢?
答: 能否卸載需要看 INF 檔案裡面是否有卸載的區段,例如使用 NSIS 卸載 Windows Messenger 可以這樣:
ExecWait "RunDll32 advpack.dll,LaunchINFSection $windir/INF/msmsgs.inf,BLC.Remove"
關於 BLC.Remove 的來源,可以開啟 msmsgs.inf 檔案後,能找到名稱為 BLC.Remove 的區段,該區段用於卸載。區段的名稱是編寫者自己定製的。不同的inf檔案,區段名也可能不同。
其他的 *.inf 檔案也可以按照此類做法。
問: 1. 我做了一個可同時在簡繁英下執行的安裝程式。 但有個很大的困惑。
剛開始時做的是簡體中文版,在簡中下當然沒問題,但在英/繁下,建立的中文程式組名和寫註冊表時顯示的是亂碼。 於是想到寫一個三者皆適合的安裝程式。
我的做法是這樣的,在涉及到建立中文程式組和寫註冊表時,加入一個判斷,如果英文或繁體,則分別建立英文檔案名稱和big5內碼檔案名稱。 但在繁體winxp和英文win2k下測試後,發現根本無法正常建立程式組,也無法正常產生uninstall.exe檔案。 而寫入註冊表的中文字元,也不能在繁體系統的註冊表中正常顯示,而是亂碼。
請教高手,這種多語言環境下該怎麼處理,才能正常顯示呢? 總不能全部都給建立成英文的吧?
2. 另外有個小問題,如何讓nsis做的安裝程式不顯示具體的安裝檔案名稱,而只顯示“正在複製檔案……”? 象foobar那樣,可惜foobar也有個顯示詳細情況的按鈕,我想在複製檔案過程中完全不顯示和提示被複製的檔案情況。
答: 1. 最簡單的處理辦法就是給需要處理的資源進行一個定義,然後使用 LangString 定義不同的資源。給個樣本:
Caption "$(CAPTION)"
LangString CAPTION ${1033} "DreamMail Installation"
LangString CAPTION ${2052} "DreamMail 安裝嚮導"
LangString CAPTION ${1028} "DreamMail 杆翾舊"
2. 可以使用 DetailPrint ,樣本,
DetailPrint "正在複製檔案..."
問: NSIS對於安裝卸載的ICO表徵圖大小有什麼要求?編譯的時候出現以下錯誤提示,
Error finding icon resources: installer, uninstaller icon size mismatch - see the Icon instructions documentation for more information -- failing!
答: 只要保證安裝表徵圖與卸載表徵圖大小相同即可。
問: 如何屏蔽如中的安裝程式校正。
答: CRCCheck on|off|force
指定安裝前安裝程式是否對自身執行一個 CRC。注意,如果使用者使用了 /NCRC 命令列參數,且你沒有指定 force 參數時,不會執行 CRC,這樣有可能導致使用者安裝一個損壞的安裝程式。
安裝程式 CRC 校正是預設開啟的。可以在指令碼中用 CRCCheck off 來預設禁止安裝程式的 CRC 校正。不過這樣做正如解釋上說的可能安裝會出現問題。作漢化的最好加上校正,免得安裝程式的問題變成你漢化品質的問題。
附圖:
問: 在安裝的時候不是可以選擇多種語言嗎?但是我怎樣實現當選擇英文時就裝英文版,選擇中文時就裝中文版?
答: 使用以下指令碼,
StrCmp $LANGUAGE ${LANG_SIMPCHINESE} 0 +3
File "你需要安裝的中文檔案"
Goto lbl_finish
File "你需要安裝的英文檔案"
lbl_finish:
問: 組件A 組件B 組件C 均為可選,A可單獨安裝,B或者C被選擇的時候A必須被選擇
答: 以下代碼,
Section "組件 A" aaa
detailprint "A"
SectionEnd
Section "組件 B" bbb
detailprint "B"
SectionEnd
Section "組件 C" ccc
detailprint "C"
SectionEnd
Function .onSelChange
SectionGetFlags ${bbb} $0
SectionGetFlags ${ccc} $1
IntOp $0 $0 & 1
IntOp $1 $1 & 1
IntCmp $0 1 0 +2
SectionSetFlags ${aaa} 1
IntCmp $1 1 0 +2
SectionSetFlags ${aaa} 1
FunctionEnd
解釋:SectionGetFlags 表示擷取某區段的flags狀態(就是是否被勾選,選中傳回值為1,反之為0)
SectionGetFlags ${bbb} $0 表示擷取序號為${bbb}的區段的Flags狀態並把傳回值輸出到變數 $0,C 區段相同。
接著就是 StrCmp ,解釋同上樓。
SectionSetFlags ${aaa} 1 表示設定序號為 ${aaa} 區段的 Flags 狀態為 1,即勾選。
問: 如果是這樣寫的時候就可以在左邊顯示頁首位元影像
!define MUI_ABORTWARNING
!define MUI_ICON "${NSISDIR}/Contrib/Graphics/Icons/modern-install.ico"
!define MUI_UNICON "${NSISDIR}/Contrib/Graphics/Icons/modern-uninstall.ico"
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "f:/11.bmp"
會顯示如附圖1。會靠左,但是如果把 MUI_HEADERIMAGE 換成 MUI_HEADERIMAGE_RIGHT 就無法顯示位元影像,只能出現安裝表徵圖了,如附圖2。
答: 把插入的headerimage圖片放到右邊(預設是在左邊)
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_RIGHT
!define MUI_HEADERIMAGE_BITMAP "include/resource/modern-header.bmp"
而不是你所說的修改 !define MUI_HEADERIMAGE,應該是在這句下面添加 !define MUI_HEADERIMAGE_RIGHT
附圖1:
附圖2:
問: 怎麼讓 "許可協議"頁面的標題列,如程式中的“MutliPages 示範”修改為“MutliPages 示範:許可協議”,如附圖。
答: 首先建立一個函數,如下。
Function LicensePagePre
SendMessage $HWNDPARENT ${WM_SETTEXT} 0 "STR:我愛你"
FunctionEnd
然後在協議頁面句子
!insertmacro MUI_PAGE_LICENSE "c:/path/to/licence/YourSoftwareLicence.txt"
之前加入如下語句
!define MUI_PAGE_CUSTOMFUNCTION_PRE LicensePagePre
附圖:
問: 比如,我把 a.exe 用nsis封裝好,安裝到 c:/helloLib/a.exe,完成後,想把c:/helloLib/添加到 系統內容變數的 path裡頭,這樣,在任何地方輸入 a.exe可執行。如何將路徑添加到 系統內容變數中?
答:以下代碼實現:
ReadRegStr $0 HKLM "SYSTEM/CurrentControlSet/Control/Session Manager/Environment" "Path"
WriteRegExpandStr HKLM "SYSTEM/CurrentControlSet/Control/Session Manager/Environment" "Path" "$0;C:/hellolib"
另類方法一: 寫註冊表,如
[HKEY_CLASSES_ROOT/Applications/a.exe/shell/open/command]
@="yourpath/a.exe"
另類方法二:
[HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersion/App Paths/a.exe]
@="c:/helloLib/a.exe"
問: 在NSIS中如何才能做到根據對於註冊表索引值的判斷決定是否寫入字串,如果判斷出某個key存在,則寫入相應的字串,如果不存在,則不寫入字串。例如:我先要判斷 “ HKLM SOFTWARE/nsis”這個key存不存在。如果存在則寫入字串“DispName:nsis”,應該是用“WriteRegStr HKLM "SOFTWARE/nsis" "DispName" "nsis"”。如果不存在這個key,則不寫入註冊表,繼續下面的安裝。
答: 以下代碼實現,
ReadRegStr $0 HKLM SOFTWARE/nsis ""
IfErrors 0 +2
Goto +2
WriteRegStr HKLM "SOFTWARE/nsis" "DispName" "nsis"
問: 如何製作安裝包的時候需要調用系統函數來檢測當前安裝包啟動並執行作業系統的內碼頁。
答: 以下代碼顯示系統語言
System::Call "Kernel32::GetSystemDefaultLangID(v ..) i .s"
Pop $0
IntOp $0 $0 & 0xFFFF
MessageBox MB_OK $0
問: 如何用NSIS註冊字型?
答: 以下代碼,
!include WinMessages.nsh
Section "MainSection" SEC01
File /oname=$FONTS/tahoma.ttf tahoma.ttf
Push "$FONTS/tahoma.ttf"
System::Call "Gdi32::AddFontResource(t s) i .s"
Pop $0
IntCmp $0 0 0 +2 +2
MessageBox MB_OK "註冊字型失敗"
SendMessage ${HWND_BROADcast} ${WM_FONTCHANGE} 0 0
SectionEnd
問: 如何用 NSIS 安裝IME。
答: 以下代碼,
SetOutPath $SYSDIR
File WBIME.ime
Push "五筆IME"
Push "$SYSDIR/WBIME.ime"
System::Call "Imm32::ImmInstallIME(t s, t s) i .s"
System::Call "Imm32::ImmIsIME(i s) i .s"
Pop $0
IntCmp $0 1 0 +3 +3
MessageBox MB_OK "IME安裝成功"
Goto +2
MessageBox MB_OK "IME安裝失敗"