程序的三種基本結構包括:順序結構、分支結構、循環結構。順序結構是最基本的結構,本文主要說明了如何在NSIS腳本中寫出分支結構和循環結構。less
最基本的分支結構和循環結構能夠用StrCmp命令和Goto命令組成,但經過這種方式寫出的代碼可讀性極差且難以調試。此時咱們就須要用到頭文件 LogicLib.nsh 中的功能了。工具
下面是一個示例程序,在「MyProgram」區域中輸入咱們要調試的代碼:
oop
!define DEBUG_PATH "E:\NSIS_Test\TmpProgram" !define OUTPUT_PATH "E:\NSIS_Test\Output" !define INSTALL_PATH "E:\NSIS_Test\Output" !include LogicLib.nsh Name "NSIS_VariableConstants_Test" Caption "NSIS_VariableConstants_Test" InstallDir ${INSTALL_PATH} OutFile "Galatea.exe" Section "My Program" SetOutPath ${OUTPUT_PATH} File /r "${DEBUG_PATH}\*.*" ; ----------------- 在這裏輸入要調試的代碼 ----------------- SectionEnd
我使用 HM NSIS Edit 2.0.3 工具編輯NSIS腳本,使用編譯工具 makensis.exe(版本號2.46) 進行編譯。spa
點擊 HM NIS Edit 中「NSIS菜單」下的「編譯並運行」,即編譯nsi文件並運行安裝包。調試
LogicLib.nsh 中用於邏輯控制的語句,我都逐個寫了例子,詳見下文。
code
例1.1:If - ElseIf - Else - EndIfit
標準的 If 語句分支結構
io
var /GLOBAL test1 StrCpy $test1 'a' ${If} $test1 == 'a' DetailPrint '$$test1 的值爲 a' ${ElseIf} $test1 == 'b' DetailPrint '$$test1 的值爲 b' ${Else} DetailPrint '$$test1 的值爲 $test1' ${EndIf}
運行結果:編譯
$test1 的值爲 a
例1.2:IfNot - Else - EndIftest
IfNot 判斷其後的表達式運算結果是否爲假,與 If 的判斷規則相反
var /GLOBAL test2 StrCpy $test2 'z' ${IfNot} $test2 == 'a' DetailPrint '$$test2 的值不爲 a' ${Else} DetailPrint '$$test2 的值爲 $test2' ${EndIf}
運行結果:
$test2 的值不爲 a
例1.3:If - ElseIf - ElseIfNot - EndIf
ElseIfNot 判斷其後的表達式運算結果是否爲假,與 ElseIf 的判斷規則相反
var /GLOBAL test3 StrCpy $test3 'b' ${If} $test3 == 'a' DetailPrint '$$test3 的值爲 a' ${ElseIfNot} $test3 == 'b' DetailPrint '$$test3 的值不爲 b' ${Else} DetailPrint '$$test3 的值爲 $test3' ${EndIf}
運行結果:
$test3 的值爲 b
例1.4:IfNot & Unless
Unless 與 IfNot 是等價的
var /GLOBAL test4 StrCpy $test4 'z' ${Unless} $test4 == 'a' DetailPrint '$$test4 的值不爲 a' ${Else} DetailPrint '$$test4 的值爲 $test4' ${EndUnless}
運行結果:
$test4 的值不爲 a
例1.5:ElseIfNot & ElseUnless
ElseUnless 與 ElseIfNot 是等價的
var /GLOBAL test5 StrCpy $test5 'b' ${If} $test5 == 'a' DetailPrint '$$test5 的值爲 a' ${ElseUnless} $test5 == 'b' DetailPrint '$$test5 的值不爲 b' ${Else} DetailPrint '$$test5 的值爲 $test5' ${EndIf}
運行結果:
$test5 的值爲 b
例2.1:AndIf & AndIfNot & AndUnless
AndIf 的邏輯,是若是前面的 If 表達式結果爲真,且當前的表達式結果也爲真,才繼續執行它下轄代碼塊中的語句。
AndIfNot 的邏輯,是若是前面的 If 表達式結果爲真,且當前的表達式結果爲假,才繼續執行它下轄代碼塊中的語句。
AndUnless 功能同 AndIfNot。
var /GLOBAL test6 StrCpy $test6 'a' ${If} $test6 == 'a' DetailPrint '$$test6 的值爲 a' ${AndIf} $test6 != 'b' DetailPrint '$$test6 的值不爲 b' ${AndIfNot} $test6 == 'b' DetailPrint '$$test6 的值不爲 b' ${AndUnless} $test6 == 'b' DetailPrint '$$test6 的值不爲 b' ${EndIf}
運行結果:
$test6 的值爲 a $test6 的值不爲 b $test6 的值不爲 b $test6 的值不爲 b
例2.2:OrIf & OrIfNot & OrUnless
AndIf 的邏輯,是若是前面的 If 表達式結果爲假,且當前的表達式結果爲真,才繼續執行它下轄代碼塊中的語句。若是前面 If 表達式結果爲真,也不會進入到它下轄的代碼塊中。
AndIfNot 的邏輯,是若是前面的 If 表達式結果爲假,且當前的表達式結果也爲假,才繼續執行它下轄代碼塊中的語句。若是前面 If 表達式結果爲真,也不會進入到它下轄的代碼塊中。
OrUnless 功能同 OrIfNot。
var /GLOBAL test7 StrCpy $test7 'z' ${If} $test7 == 'a' DetailPrint '$$test7 的值爲 a' ${OrIf} $test7 == 'b' DetailPrint '$$test7 的值爲 b' ${OrIfNot} $test7 != 'b' DetailPrint '$$test7 的值爲 b' ${OrUnless} $test7 != 'b' DetailPrint '$$test7 的值爲 b' ${Else} DetailPrint '$$test7 的值爲 $test7' ${EndIf}
運行結果:
$test7 的值爲 z
例3.1:IfThen
IfThen 語句,判斷其後的表達式結果是否爲真,執行第三個參數中指定的命令
var /GLOBAL test8 StrCpy $test8 'a' ${IfThen} $test8 == 'a' ${|} Goto x1 ${|} x1: DetailPrint 'x1' Goto endOfxy1 y1: DetailPrint 'y1' Goto endOfxy1 endOfxy1: DetailPrint 'endOfxy1'
運行結果:
x1 endOfxy1
例3.2:IfNotThen
IfNotThen 的邏輯與 IfThen 相反,判斷其後的表達式結果是否爲假,執行第三個參數中指定的命令
var /GLOBAL test9 StrCpy $test9 'b' ${IfNotThen} $test9 == 'a' ${|} Goto y2 ${|} x2: DetailPrint 'x2' Goto endOfxy2 y2: DetailPrint 'y2' Goto endOfxy2 endOfxy2: DetailPrint 'endOfxy2'
運行結果:
y2 endOfxy2
例4.1:IfCmd
判斷其後執行命令(如MessageBox)的結果爲指定結果時,執行指定的命令。
以下面這段代碼中,若是在彈出的 MessageBox 中點擊了「是」,則會跳轉到y3
${IfCmd} MessageBox MB_YESNO "MY_YESNO" /SD IDYES IDYES ${||} Goto y3 ${|} x3: DetailPrint 'x3' Goto endOfxy3 y3: DetailPrint 'y3' Goto endOfxy3 endOfxy3: DetailPrint 'endOfxy3'
點擊「是」時運行結果:
y3 endOfxy3
例5.1:Select - Case - CaseElse - EndSelect
Select分支語句無需在每個分支的最後添加 Break 標記,每一個分支執行完畢後自動跳至 EndSelect
var /GLOBAL test10 StrCpy $test10 'b' ${Select} $test10 ${Case} 'a' DetailPrint '$$test10 的值爲 a' ${Case} 'b' DetailPrint '$$test10 的值爲 b' ${Case} 'c' DetailPrint '$$test10 的值爲 c' ${CaseElse} DetailPrint '$$test10 的值爲 $test10' ${EndSelect}
運行結果:
$test10 的值爲 b
例5.2:Select - Case - Default - EndSelect
Default 的功能與 CaseElse 是同樣的
var /GLOBAL test11 StrCpy $test11 'd' ${Select} $test11 ${Case} 'a' DetailPrint '$$test11 的值爲 a' ${Case} 'b' DetailPrint '$$test11 的值爲 b' ${Case} 'c' DetailPrint '$$test11 的值爲 c' ${Default} DetailPrint '$$test11 的值爲 $test11' ${EndSelect}
運行結果:
$test11 的值爲 d
例6.1:Switch - Case - CaseElse - EndSwitch
Switch 分支語句相似C語言的 switch 語句,若是不在一個 Case 的末尾添加 Break 標記,程序會一直向下執行其餘 Case 中的部分。
var /GLOBAL test12 StrCpy $test12 'b' ${Switch} $test12 ${Case} 'a' DetailPrint '$$test12 的值爲 a' ${Break} ${Case} 'b' DetailPrint '$$test12 的值爲 b' ${Break} ${Case} 'c' DetailPrint '$$test12 的值爲 c' ${Break} ${CaseElse} DetailPrint '$$test12 的值爲 $test12' ${EndSwitch}
運行結果:
$test12 的值爲 b
例6.2:Switch - Case - Default - EndSwitch
Default 的功能與 CaseElse 是同樣的
var /GLOBAL test13 StrCpy $test13 'b' ${Switch} $test13 ${Case} 'a' DetailPrint '$$test13 的值爲 a' ${Break} ${Case} 'b' DetailPrint '$$test13 的值爲 b' ${Break} ${Case} 'c' DetailPrint '$$test13 的值爲 c' ${Break} ${Default} DetailPrint '$$test13 的值爲 $test13' ${EndSwitch}
運行結果:
$test13 的值爲 b
例6.3:Switch - Case - CaseElse - EndSwitch WithOut Break
若是不在一個 Case 的末尾添加 Break 標記,程序會一直向下執行其餘 Case 中的部分。
var /GLOBAL test14 StrCpy $test14 'a' ${Switch} $test14 ${Case} 'a' DetailPrint '$$test14 的值爲 a' ${Case} 'b' DetailPrint '$$test14 的值爲 b' ${Case} 'c' DetailPrint '$$test14 的值爲 c' ${Default} DetailPrint '$$test14 的值爲 $test14' ${EndSwitch}
運行結果:
$test14 的值爲 a $test14 的值爲 b $test14 的值爲 c $test14 的值爲 a
例7.1:While - EndWhile 循環
While 循環,只要後面的表達式爲真,就一直循環下去
StrCpy $R1 0 ${While} $R1 < 5 IntOp $R1 $R1 + 1 DetailPrint $R1 ${EndWhile}
運行結果:
1 2 3 4 5
例7.2:DoWhile - Loop 循環
DoWhile 循環,用法同While
StrCpy $R1 0 ${DoWhile} $R1 < 5 IntOp $R1 $R1 + 1 DetailPrint $R1 ${Loop}
運行結果:
1 2 3 4 5
例7.3:DoUntil - Loop 循環
DoUntil 循環,只要後面的表達式值爲假,就一直循環下去
StrCpy $R1 0 ${DoUntil} $R1 >= 5 IntOp $R1 $R1 + 1 DetailPrint $R1 ${Loop}
運行結果:
1 2 3 4 5
例7.4:Do - LoopWhile 循環
Do 循環,先執行指定代碼,再判斷若是 LoopWhile 後面的表達式爲真,就一直循環該段代碼
StrCpy $R1 0 ${Do} IntOp $R1 $R1 + 1 DetailPrint $R1 ${LoopWhile} $R1 < 5
運行結果:
1 2 3 4 5
例7.5:Do - LoopUntil 循環
Do 循環,先執行指定代碼,再判斷若是 LoopUntil 後面的表達式爲假,就一直循環該段代碼
StrCpy $R1 0 ${Do} IntOp $R1 $R1 + 1 DetailPrint $R1 ${LoopUntil} $R1 >= 5
運行結果:
1 2 3 4 5
例7.6:Break & Continue
Break 和 Continue 可用於退出全部類型的循環
StrCpy $R1 0 ${While} $R1 < 5 IntOp $R1 $R1 + 1 ${If} $R1 == 2 ${Continue} ${ElseIf} $R1 == 4 ${Break} ${EndIf} DetailPrint $R1 ${EndWhile}
運行結果:
1 3
例7.7:ExitDo
ExitDo 可用於退出 Do - LoopWhile、Do - LoopUntil、DoWhile、DoUntil 四類循環
StrCpy $R1 0 ${Do} IntOp $R1 $R1 + 1 ${If} $R1 == 4 ${ExitDo} ${EndIf} DetailPrint $R1 ${LoopWhile} $R1 < 5
運行結果:
1 2 3
例7.8:ExitWhile
ExitWhile 只能用於退出 While 循環
StrCpy $R1 0 ${While} $R1 < 5 IntOp $R1 $R1 + 1 ${If} $R1 == 4 ${ExitWhile} ${EndIf} DetailPrint $R1 ${EndWhile}
運行結果:
1 2 3
例8.1:For - Next 循環
For 循環的第一個參數爲循環變量,第二個參數爲該遍歷進入循環的初始值,當該變量的值在執行循環的過程當中與第三個參數相等時,循環退出。
${For} $R1 1 5 DetailPrint $R1 ${Next}
運行結果:
1 2 3 4 5
例8.2:ForEach 循環
ForEach 循環與 For 循環的不一樣之處在於,ForEach 循環還有第4、五個參數,用於指定循環的步長,第四個參數用於指定步長的正負(+、-),第五個參數用於指定步長的絕對值。
${ForEach} $R1 1 5 + 1 DetailPrint $R1 ${Next} ${ForEach} $R1 10 2 - 2 DetailPrint $R1 ${Next}
運行結果:
1 2 3 4 5 10 8 6 4 2
例8.3:Break & Continue
Break 和 Continue 可用於退出全部類型的循環
${For} $R1 1 5 ${If} $R1 == 2 ${Continue} ${ElseIf} $R1 == 4 ${Break} ${EndIf} DetailPrint $R1 ${Next}
運行結果:
1 3
例8.4:ExitFor
ExitFor 可用於退出 For 循環與 ForEach 循環
${For} $R1 1 5 ${If} $R1 == 4 ${ExitFor} ${EndIf} DetailPrint $R1 ${Next}
運行結果:
1 2 3 10 8 6
END