NSIS打包脚本的编写
变量分为局部变量和全局变量( 变量的声明使用var 全局变量再加上/GLOBAL)
Var example
Function testVar
# 函数内部定义变量必须是全局变量。不能定义局部变量
Var /GLOBAL example2
# 变量的使用:$+变量名
# 变量的赋值:使用StrCpy函数
StrCpy $example "example value"
StrCpy $example2 "another example value"
FunctionEnd
# 函数的调用: Call FuncName
# 使用在卸载函数中的自定义函数,函数名称必须以un.开头,包括嵌套的函数,也是这个规则
Call testVar
内置的变量,可直接使用,主要目的是跨函数调用。
NSIS还内置了一系列变量,如$0~$9,$R0 ~ $R9,这些变量无需声明即可直接使用。其中,$0常用于临时存储地址或回调函数的参数。这些变量在脚本执行过程中可以存储和传递数据,方便实现各种复杂的安装逻辑。$R0 一般是栈内存首个寄存器。
#获取安装默认语言
System::Call 'kernel32::GetUserDefaultUILanguage() i .r0'
System::Call 'kernel32::GetLocaleInfoA(i 1024, i ${LOCALE_SNATIVELANGNAME}, t .r1, i ${NSIS_MAX_STRLEN}) i r0'
System::Call 'kernel32::GetLocaleInfoA(i 1024, i ${LOCALE_SNATIVECTRYNAME}, t .r2, i ${NSIS_MAX_STRLEN}) i r0'
System::Call 'kernel32::GetLocaleInfoA(i 1024, i ${LOCALE_SLANGUAGE}, t .r3, i ${NSIS_MAX_STRLEN}) i r0'
;MessageBox MB_OK|MB_ICONINFORMATION "Your System LANG Code is: $0. $\r$\nYour system language is: $1. $\r$\nYour system language is: $2. $\r$\nSystem Locale INFO: $3."
Pop $0
IntOp $0 $0 & 0xFFFF
;MessageBox MB_OK|MB_ICONINFORMATION "Your System LANG Code is: $0. "
${if} $0 == 2052
StrCpy $R4 "0" #0:汉语 1:英语 2:繁体中文
${elseif} $0 == 1028
StrCpy $R4 "2" #0:汉语 1:英语 2:繁体中文
${elseif} $0 == 3076
StrCpy $R4 "2" #0:汉语 1:英语 2:繁体中文
${elseif} $0 == 5124
StrCpy $R4 "2" #0:汉语 1:英语 2:繁体中文
${else}
StrCpy $R4 "1" #0:汉语 1:英语 2:繁体中文
${endif}
$R4存储的是多语言的标志。
静态变量,函数编译期已经确定了,运行期不会被改变的变量。
使用的时候除了固定前缀$符号,要再配合花括号{}使用。比如:${EXE_NAME}
内置语法命令,也是使用${}包裹指定的命令,并且命令是首字母大写。如:
${If}
${Endif}
当然,不推荐手写,使用vscode工具,安装NSIS语言识别插件,我们输入If,首字母大写,就会有语法提示,选到符合的语言上面,自动就出来了。其他语法类似。
语法缩进要严格执行,否则会出错。
常用功能
# 文件删除,文件夹级联删除
Delete "文件名称"
RMDir "文件夹"
# 跳转语句 Goto
# label_to_jump_to | +offset| -offset| user_var(target)
Goto label # 跳转到指定的标签label对应的代码段,最常用
Goto +2 # 相对偏移量,跳转到后2条指令处
Goto -2 # 相对偏移量,跳转到前2条指令处
Goto $0 # $0如果有值,跳转到指定的地址(如果指定了用户变量,则跳转到绝对地址(通常您希望从GetLabelAddress之类的函数获取此值))
# 使用nsProcess插件查杀程序
Function un.KillExe
Var /GLOBAL myexe
Exch $R0
StrCpy $myexe $R0
# 查进程
nsProcess::_FindProcess $myexe
Pop $R0
${If} $R0 == 0
# 杀进程
nsProcess::_KillProcess $myexe
pop $R0
# 失败
${If} $R0 != 0
${If} $R4 == "0"
StrCpy $R8 "请手动关闭$myexe"
StrCpy $R9 "确定"
${ElseIf} $R4 == "2"
StrCpy $R8 "請手動關閉$myexe"
StrCpy $R9 "確定"
${Else}
StrCpy $R8 "Please Close $myexe manually."
StrCpy $R9 "yes"
${EndIf}
StrCpy $R7 "0"
Call un.ShowMsgBox
${EndIf}
${EndIf}
FunctionEnd
## 模拟在卸载程序中执行删除文件操作,区分处理删除成功和失败的逻辑
Function un.ErrorHandler
MessageBox MB_OKCANCEL "ErrorHandler!"
FunctionEnd
Function un.myFunc
Exch $R0
Var /GLOBAL myExe
StrCpy $myExe $R0
MessageBox MB_OK "$myExe"
# IfErrors jump_to_if_error [jump_to_if_no_error]
ClearErrors # 清楚错误,否则后面判断会不准确
Delete "d:\\cccc.txt"
IfErrors 0 +3
Call un.ErrorHandler # 0, +1
Goto +2 # +2
MessageBox MB_OK "没有错误" # +3
MessageBox MB_OK "主流程结束了"
FunctionEnd
# 执行具体的卸载
Function un.onUninstall
push 88
Call un.myFunc
Goto InstallAbort
# do stuff
InstallAbort:
FunctionEnd
# Return语句,退出函数或段
Function func
StrCmp $0 "return now" 0 +2
Return
# do stuff
FunctionEnd