奇怪的偏移行为

Weird behaviour of offset

我有以下代码

ClearErrors
ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Office\ClickToRun\Configuration" "ProductReleaseIds"
IfErrors done                       ;+19 if error
${StrLoc} $R1 $R0 "365" ">"
    StrCmp $R1 "" next 0            ;+8 if substring is not found
    ReadRegStr $R1 HKLM "SOFTWARE\Microsoft\Office\ClickToRun\Configuration" "Platform"
        ${If} $R1 = "x86"
            StrCpy $R1 "365x32"
        ${Else}
            StrCpy $R1 "365x64"
        ${EndIf}
        Goto found_${ID}
next: ${StrLoc} $R1 $R0 "2019" ">"
    StrCmp $R1 "" done 0            ;+8 if substring is not found
    ReadRegStr $R1 HKLM "SOFTWARE\Microsoft\Office\ClickToRun\Configuration" "Platform"
        ${If} $R1 = "x86"
            StrCpy $R1 "2019x32"
        ${Else}
            StrCpy $R1 "2019x64"
        ${EndIf}
        Goto found_${ID}
done: ClearErrors

即使在代码编译期间没有 errors/warnings 上升,代码行为也不符合预期。经过 2 小时的“富有想象力”的调试,我明白了我遇到的奇怪行为的原因。

在最后的代码中,我使用了“下一步”和“完成”标签,所有问题都消失了!一开始我用数字来跳跃(请查看注释字符串中应该有效但无效的数字!)。

有谁知道为什么那些跳跃的数字是错误的吗?

在正常情况下,我发誓我数到20没有问题,但似乎并非如此:)

你不应该使用偏移量来跳过宏,因为你不知道它们包含多少指令(并且可能在 NSIS 版本之间改变)。

在您的例子中,StrLoc 和 If/Else/EndIf 是宏。

标签在生成的安装程序中的开销为零,应该在大多数地方使用 (and/or If/EndIf)。直接偏移在可能多次包含在同一 function/section 中的宏中很有用,您不能在其中使用 If/EndIf/While(罕见),但它很快就会失控。您可以使用 !define MyLabel L${__COUNTER__} 之类的东西为这样的宏创建标签:

!macro Test
!define MyLabel L${__COUNTER__}
...
StrCmp   ${MyLabel}_end
...
${MyLabel}_end:
!undef MyLabel
!macroend