向所有阅读者致以问候:)目标中心与文章的内容不符,但应做什么...-没有针对此目的的主题,但最适合的主题是“ C”,因为 它的读者将最容易理解所写内容。文章目的
一种解决使用NSIS编写安装程序/卸载程序时控制全局变量问题的选项。小介绍
在编写nsis代码时,程序员可以使用范围为整个项目的全局变量。它们只有20个:$ 0- $ 9和$ R0- $ R9。使用它们非常方便,因为 这样就无需引入正式用于解决目标问题的其他变量。我正式地说是因为 任何nsis变量都具有全局范围,并且如果它们之间有所不同,则仅使用限定符const(用C / C ++术语来讲):!define variable1 ''value 1''
特征:- 全局范围的静态变量;
- 声明后初始化;
- 联系方式:$ {variable1}
Var variable2
特征:- 全球范围内的动态变量;
- 它通过代码在任何地方声明,但在第一个调用之上;
- 它可以根据需要进行多次初始化,但是只能在功能块和宏内部进行初始化。
- 访问方法:$ variable2
因此,考虑到以上特征,很明显,除静态变量外,任何目标变量的创建都是很难的,因为 默认情况下,全局变量已经存在,它们足以满足任何需求(如果没有,您需要向程序员询问“适当的”问题),而其他任何变量很可能只会阻塞代码。问题描述
但麻烦的是,此代码始终会生成错误:
Function F1
StrCpy $0 "vladimir"
FunctionEnd
Function F2
StrCpy $0 "alexei"
Call F1
${If} $0 == "alexei" ;
;
${EndIf}
FunctionEnd
您可以举很多例子,在nsis上进行编程的技术人员可以最大程度地解决此问题:- 有人刚刚仔细观察了所有变量(这类人需要建立纪念碑)。
- 有人,主要是各种插件的创建者,每次想要使用提供的任何变量,都将其推入堆栈,在使用结束后,他们通过调用Pop返回主值。
- 如上所述,有人通过Var产生了变量。
无论如何,它们都面临着缺少通用机制的问题,该通用机制解决了监视全局变量状态的问题。在这里,我允许自己为她(问题)提供一个通用的解决方案。解决问题
首先,指向NSISList的链接是一个插件,它引入了使用列表类型数据结构的功能,该结构必须采用与C ++中的std :: list相同的方式进行。第二步是问题解决机制的源代码:
!verbose 3
!include NSISList.nsh ; *
!define InitDump "!insertmacro _InitDump"
!macro _InitDump
!ifdef __UNINSTALL__
Call un.InitDump
!else
Call InitDump
!endif
!macroend
!macro Func_InitDump un
Function ${un}InitDump
# $0-$9
${List.Create} d0
${List.Create} d1
${List.Create} d2
${List.Create} d3
${List.Create} d4
${List.Create} d5
${List.Create} d6
${List.Create} d7
${List.Create} d8
${List.Create} d9
# $R0-$R10
${List.Create} dR0
${List.Create} dR1
${List.Create} dR2
${List.Create} dR3
${List.Create} dR4
${List.Create} dR5
${List.Create} dR6
${List.Create} dR7
${List.Create} dR8
${List.Create} dR9
FunctionEnd
!macroend
!insertmacro Func_InitDump ""
!insertmacro Func_InitDump "un."
!define Dump "!insertmacro _Dump"
!macro _Dump
!ifdef __UNINSTALL__
Call un.Dump
!else
Call Dump
!endif
!macroend
!macro Func_Dump un
Function ${un}Dump
# $0-$9
${List.Add} d0 $0
${List.Add} d1 $1
${List.Add} d2 $2
${List.Add} d3 $3
${List.Add} d4 $4
${List.Add} d5 $5
${List.Add} d6 $6
${List.Add} d7 $7
${List.Add} d8 $8
${List.Add} d9 $9
# R0-R9
${List.Add} dR0 $R0
${List.Add} dR1 $R1
${List.Add} dR2 $R2
${List.Add} dR3 $R3
${List.Add} dR4 $R4
${List.Add} dR5 $R5
${List.Add} dR6 $R6
${List.Add} dR7 $R7
${List.Add} dR8 $R8
${List.Add} dR9 $R9
FunctionEnd
!macroend
!insertmacro Func_Dump ""
!insertmacro Func_Dump "un."
!define Undump "!insertmacro _Undump"
!macro _Undump
!ifdef __UNINSTALL__
Call un.Undump
!else
Call Undump
!endif
!macroend
!macro Func_Undump un
Function ${un}Undump
# $0-$9
${List.Pop} $0 d0
${List.Pop} $1 d1
${List.Pop} $2 d2
${List.Pop} $3 d3
${List.Pop} $4 d4
${List.Pop} $5 d5
${List.Pop} $6 d6
${List.Pop} $7 d7
${List.Pop} $8 d8
${List.Pop} $9 d9
# R0-R9
${List.Pop} $R0 dR0
${List.Pop} $R1 dR1
${List.Pop} $R2 dR2
${List.Pop} $R3 dR3
${List.Pop} $R4 dR4
${List.Pop} $R5 dR5
${List.Pop} $R6 dR6
${List.Pop} $R7 dR7
${List.Pop} $R8 dR8
${List.Pop} $R9 dR9
FunctionEnd
!macroend
!insertmacro Func_Undump ""
!insertmacro Func_Undump "un."
第三步是对其工作方式的简短描述:从前面重写全局变量$ 0- $ 9,$ R0- $ R9本身的危险的角度出发,将完全保护根据先前主代码注释所描述的规则创建和设计的每个函数,因此-由于违反了调用函数的逻辑。它是这样的:- F1函数本身不是直接调用的,
Call F1
并通过宏包装器${F1} [paramIn1 [paramIn2]...[paramInN]] [paramOut1 [paramOut2]...[paramOutM]]
- 甚至在直接调用函数之前,它都会被调用
${Dump}
结果,变量$ 0- $ 9,$ R0- $ R9的当前值保存在转储中。在幕后,他有很多列表,每个列表都与它的目标变量相关。 - 将函数的所有目标变量加载到堆栈中
Push ${paramIn1} Push ${paramIn2} ... Push ${paramInN}
(如果需要); - 该函数将被调用;
- 该函数将执行其逻辑并退出;
- 电话会发生
${Undump}
结果,将恢复存储在$ {Dump}的最后一次调用中的全局变量的值; - 从堆栈中卸载函数结果
Pop ${paramOut1} Pop ${paramOut2} ... Pop ${paramOutM}
(如果需要); - F1函数上的宏包装程序将完成其工作。
结论
结果,我们得到了用于安全编写nsis代码的通用设计。您甚至可以说,它不会带来任何缺点,只是编译后的代码可以工作约30毫秒。慢点。希望这可以使某人的生活更轻松:)谢谢!