NSIS ${LineRead}读取返回数字而非文本,求问题排查与解决
问题排查与解决方案
我一眼就看穿了问题的核心——你对NSIS的${LineRead}宏用法存在误解,同时代码里还有几处语法和逻辑错误,导致返回的是错误码而非预期的文本内容。下面一步步拆解问题并给出修复方案:
1. ${LineRead}调用错误:返回错误码而非文本
你当前的调用是:
${LineRead} "$TEMP\addonInstallerPreFolder\addons\postponeLog.txt" "$i - $i" $0
这里的第二个参数是字符串"$i - $i",而${LineRead}要求第二个参数是整数行号(从0开始计数)。当宏无法解析行号时,它会返回错误码:30对应的是格式错误(ERROR_BAD_FORMAT),这就是你看到数字的原因。
正确的调用应该直接传入循环变量$i作为行号:
${LineRead} "$TEMP\addonInstallerPreFolder\addons\postponeLog.txt" $i $0
2. ${ForEach}循环语法错误
你的循环定义:
${ForEach} $i 0 $lineCount + 1
${ForEach}的步长参数不需要加+号,直接写数字即可。另外,如果$lineCount是文件的总行数,你应该循环到$lineCount - 1(因为行号从0开始),否则会尝试读取不存在的行,再次触发错误码。修正后:
IntOp $lineCount $lineCount - 1 ; 先把总行数转成最大行号(0-based) ${ForEach} $i 0 $lineCount 1
3. ${StrContains}参数顺序颠倒
LogicLib中的${StrContains}宏参数顺序是:结果变量 → 要查找的字符串 → 源字符串,你写反了:
${StrContains} $0 "Success" $1 ; 错误
正确写法:
${StrContains} $1 "Success" $0 ; 把查找结果存入$1,在$0中查找"Success"
4. 删除文件夹的命令错误
Delete命令只能删除文件,要删除文件夹(包括其中的内容),必须用RmDir /r:
RmDir /r "$INSTDIR\addons\backup_$R0"
5. 变量初始化与作用域问题
你注释了; Var i,但在函数中使用$i前必须声明它。如果是全局变量,在函数外添加Var i;如果是局部变量,在函数开头用Push $i保存原有值,结束时Pop $i恢复。
完整修复后的代码
!include "${NSISDIR}\Include\LogicLib.nsh" !include "myLogger.nsh" Var i ; 声明全局变量i Function removeFolder Push $i ; 保存原有$i的值,避免污染全局变量 IntOp $i 0 0 ; 初始化循环变量为0 ; 确保行号范围正确(0-based) IntOp $lineCount $lineCount - 1 ${ForEach} $i 0 $lineCount 1 ; 正确读取指定行的文本内容到$0 ${LineRead} "$TEMP\addonInstallerPreFolder\addons\postponeLog.txt" $i $0 !insertmacro LOGGER_WRITE "DEBUG Text $0" "0" ; 正确检查$0中是否包含"Success" ${StrContains} $1 "Success" $0 ${if} $1 == 1 ; StrContains返回1表示找到,0表示未找到 Push "Success" ${else} Push "Failed" ${endif} Push $0 Call Slice Pop $R0 ${if} $revertAfter == "true" CopyFiles "$INSTDIR\addons\backup_$R0\*" "$INSTDIR\addons\$R0" !insertmacro LOGGER_WRITE "Revert Backupfolder to AddonFolder $R0" "0" ${endif} !insertmacro LOGGER_WRITE "Removed Backup folder of $R0" "0" ; 递归删除文件夹 RmDir /r "$INSTDIR\addons\backup_$R0" ${next} Pop $i ; 恢复原有$i的值 FunctionEnd
额外注意事项
- 确保
$lineCount变量正确获取了文件的总行数,可以用${LineCount}宏来获取:${LineCount} "$TEMP\addonInstallerPreFolder\addons\postponeLog.txt" $lineCount - 测试
Slice函数是否正确处理了$0的内容(比如从addon1Success中提取addon1),如果这个函数有问题,也会导致后续逻辑出错。
内容的提问来源于stack exchange,提问作者Cris Night
相关产品推荐
相关产品推荐

