NSIS腳本學習:使用 LogicLib.nsh 實現基本流程控制結構

LogicLib.nsh

程序的三種基本結構包括:順序結構、分支結構、循環結構。順序結構是最基本的結構,本文主要說明了如何在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、If 分支語句

例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、If 語句與 And 和 Or 組合而成的新關鍵字

例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、IfThen 與 IfNotThen

例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、IfCmd

例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、Select 多重分支語句

例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、Switch 多重分支語句

例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、While、Do、DoWhile、DoUntil 循環

例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、For 與 ForEach 循環

例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

相關文章
相關標籤/搜索