【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
LogicLib.nsh
程序的三种基本结构包括:顺序结构、分支结构、循环结构。顺序结构是最基本的结构,本文主要说明了如何在NSIS脚本中写出分支结构和循环结构。
最基本的分支结构和循环结构可以用StrCmp命令和Goto命令组成,但通过这种方式写出的代码可读性极差且难以调试。此时我们就需要用到头文件 LogicLib.nsh 中的功能了。
下面是一个示例程序,在“MyProgram”区域中输入我们要调试的代码:
!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) 进行编译。
点击 HM NIS Edit 中“NSIS菜单”下的“编译并运行”,即编译nsi文件并运行安装包。
LogicLib.nsh 中用于逻辑控制的语句,我都逐个写了例子,详见下文。
一、If 分支语句
例1.1:If - ElseIf - Else - EndIf
标准的 If 语句分支结构
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 - EndIf
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
二、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
三、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
四、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
五、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
六、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
七、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
八、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 循环还有第四、五个参数,用于指定循环的步长,第四个参数用于指定步长的正负(+、-),第五个参数用于指定步长的绝对值。
${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
来源:oschina
链接:https://my.oschina.net/u/1425762/blog/655817