nsis入门精解教程
时间:2009-04-20 | 作者:本站整理 | 阅读:6857NSIS (Nullsoft Scriptable Install System)是一个Open Source的Windows系统下安装程序制作程序。它提供了安装、卸载、系统设置、文件解压缩等功能。这如其名字所指出的那样,NSIS是通过它的脚本语言来描述安装程序的行为和逻辑的。NSIS的脚本语言和通常的编程语言有类似的结构和语法,但它是为安装程序这类应用所设计的。NSIS脚本通常以 nsi为扩展名,支持include功能,头文件扩展名为nsh。
NSIS的主要特点是:
- 开销小,一个完整功能的安装程序仅需要34k的额外开销。
- 支持大多数Windows平台,包括:Windows 9.x,Windows NT, Windows 2000, Windows XP, Windows 2003
- 支持三大压缩算法: Zlig, BZips, LZMA
- 支持脚本
- 支持多语言
- 支持安装界面定制
- 提供可扩展的插件接口
- 支持网络安装、补丁
- 支持无人值守的安装模式
- 此外,NSIS的license允许任何用途免费使用。
与时(fortime.net)
开发一个NSIS的安装程序通常有以下几步:
- 确定安装的功能和界面元素
- 编写NSIS脚本
- 使用NSIS提供的makensis或者makensisw程序,将步骤2编写的脚本编译成可执行的安装程序
- 调试安装程序,如果有问题退到第二步重复
随着NSIS的流行,有一些第三方的NSIS脚本开发环境出现了,如HM NIS Edit,Venis IX前者是完全开源的,后者仅对个人和非商业用途免费。在这些集成开发环境下,步骤2,3可以方便的组合在一起。
NSIS脚本的结构
NSIS脚本(下称nsi脚本)主要包含安装程序属性、页面、区段、函数。
属性用来定义安装程序的行为和界面风格,这些属性大部分是编译时刻属性,即不能在运行时刻改变。
页面是指安装程序的向导页面,示例:
Page license
Page components
Page directory
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles
区段是对应某种安装/卸载选项的处理逻辑,该段代码仅当用户选择相应的选项才被执行。卸载程序的区段名用"un."作为前缀,示例如下:
Section "Installer Section"
SectionEnd
Section "un.Uninstaller Section"
SectionEnd
在区段中可以使用很多指令用来完成诸如解压缩文件、读写注册表、创建目录、创建快捷方式等任务,但最常用的指令是SetOutPath和File,前者用于指定目的位置,后者用于指定文件。示例:
与时电脑知识库(fortime.net)
Section "My Program"
SetOutPath $INSTDIR
File "My Program.exe"
File "Readme.txt"
SectionEnd
区段名的修饰符/o表示该区段默认不选上,-表示隐藏区段(匿名区段也是隐藏区段),!表示需要粗体显示的区段。
SectionIn表示该区段和安装类型之间的关系:
SectionIn insttype_index [insttype_index] ... [RO]
RO修饰符表示不可修改。
子区段用于包含多个区段
SubSection [/e] Caption [subsection_name index output]
修饰符/e用于该子区段的所有区段是否默认展开。
函数包含了模块化的安装逻辑,在nsi脚本中函数分为两种:用户自定义函数和回调函数。用户自定义函数仅当是Call指令调用时才被执行,如果函数体中没有abort语句,则安装程序执行完了用户自定义函数,继续运行Call语句和指令。
用户自定义函数的语法如下:
Function <函数名>
# some commands
FunctionEnd
函数的调用则使用以下语法:
Call <函数名>
可见无论是函数的定义还是函数的调用都没有参数传递。通常nsi的参数传递是通过堆栈操作Pop,Push和20个寄存器变量$0~$9, $R0~$R9进行的。也可以通过全局变量完成参数传递。如:
www.fortime.net
Var input ;
Var output ;
Section bla
DeteailPrint "input is $input$\n"
Call square
DeteailPrint "square of $input is $output$\n"
SectionEnd
Function square
output = input^2
FunctionEnd
回调函数则是由在特定的时间点触发的程序段。常用的回调函数如.onInit:
Function .onInit
MessageBox MB_YESNO "This will install My Program. Do you wish to continue?" IDYES gogogo
Abort
gogogo:
FunctionEnd
NSIS对于安装逻辑定义以下回调函数:.onGUIInit、.onInit、.onInstFailed、.onInstSuccess、. onGUIEnd、.onMouseOverSection、.onRebootFailed、.onSelChange、.onUserAbort、. onVerifyInstDir
NSIS对于卸载逻辑定义以下回调函数:un.onGUIInit、un.onInit、un.onUninstFailed、un.onUninstSuccess、un.onGUIEnd、un.onRebootFailed、un.onUserAbort
nsi脚本的变量定义
nsi脚本的变量定义用Var关键字,后跟变量名,变量是全局的并且是大小写敏感的。变量引用时需要加上前缀$。
除了用户自定义的变量外,nsi脚本中与定义寄存器变量$0~$9,$R0~$R9用于参数传递,以及系统变量用于特定用途,这些变量主要有:
与时IT资讯
$INSTDIR,$OUTDIR,$CMDLINE,$LANGUAGE这些变量都是可写的。
$PROGRAMFILES,$COMMONFILES,$DESKTOP,$EXEDIR,${NSISDIR},$WINDIR,$SYSDIR,$ TEMP,$STARTMENU,$SMPROGRAMS,$SMSTARTUP,$QUICKLAUNCH,$DOCUMENTS,$SENDTO,$ RECENT,$FAVORITES,$MUSIC,$PICTURES,$VIDEOS,$NETHOOD,$FONTS,$TEMPLATES,$ APPDATA,$PRINTHOOD,$INTERNET_CACHE,$COOKIES,$HISTORY,$PROFILE,$ ADMINTOOLS,$RESOURCES,$RESOURCES_LOCALIZED,$CDBURN_AREA,$HWNDPARENT,$ PLUGINSDIR
nsi脚本中可用于调试的系统函数有MessageBoxes,DetailPrint,Dumpstate。
nsi脚本的编译器指令
nsi脚本的编译器指令主要指仅在编译时刻执行的命令。这些命令主要用来包含文件、条件化编译、定义常量、定义宏等。定义常量和宏是编译器指令最主要应用。
定义常量的示例:
!define VERSION "1.0.3"
Name "My Program ${VERSION}"
OutFile "My Program Installer - ${VERSION}.exe"
定义宏的示例:
!macro MyFunc UN
Function ${UN}MyFunc
Call ${UN}DoRegStuff
ReadRegStr $0 HKLM Software\MyProgram key
DetailPrint $0
FunctionEnd www.fortime.net
Modern UI
Modern UI是感观上模仿最新的Windows系统的界面风格,它由欢迎页面、结束页面和其他向导页面构成。
插件
nsi支持插件,通过插件可以方便的扩展NSIS安装程序的功能。NSIS插件是用C++,Delphi等语言编写的dll,在nsi脚本中调用nsi中的函数使用如下语法:
DLLName::FunctionName "参数1" "参数2" "参数3"
示例1:
nsExec::ExecToLog '"${NSISDIR}\makensis.exe" /CMDHELP'
执行makensis.exe命令,显示该命令用法。
示例2:
InstallOptions::dialog "$PLUGINSDIR\test.ini"
显示对话框
示例3:
NSISdl::download http://download.nullsoft.com/winamp/client/winamp291_lite.exe $R0
下载文件
NSIS搜索插件的策略
默认情况下NSIS在其安装目录的子目录Plugins中搜索插件,用户可以使用!addplugindir指定增加插件的目录位置。
nsi脚本的基本语法
注释
单行注释用井号"#"或分号";",跨行注释用可以用c/C++中注释语法。
数据类型
数字
数字常量可以用十进制、十六进制(0x为前缀)、八进制(0为前缀)表示,颜色用类似html的中RGB表示法,但去井号"#"。
字符串
字符串常量可以用引号引用,转意字符用"$\"作前缀。美元符号、常用转意字符换行、回车、制表符的nsi语法表示分别为:$$,$\n,$\r,$\t
续行符
nsi脚本用行尾的反斜杠"\"表示下一行和当前行逻辑上是同一行
默认头文件
如果在makensis同目录下有nsisconf.nsh文件,该文件会被自动包含,除非编译时指定/NOCONFIG选项
标号
nsi使用GOTO语句和IfErrors, MessageBox, IfFileExists及StrCmp进行程序控制流表示,标号是这些语句的目标语句。标号定义的语法:
标号:语句
标号必须定义在函数和区段中,其作用范围仅限于定义它的区段或函数。以点号"."开头的标号是全局标号。
相对跳转
nsi脚本常常使用相对跳转表示条件分枝,其语法是[+-][1-9],加号表示从当前位置往前跳转,减号则表示从当前位置往后跳转。数字表示跳转的语句条数。示例: 与时IT资讯(www.fortime.net)
Goto +4
MessageBox MB_OK "The following message will be skipped"
Goto +3
MessageBox MB_OK "You will never ever see this message box"
Goto -3
MessageBox MB_OK "Done"
页面
向导页面是NSIS安装程序中最重要的界面元素,在nsi脚本中可以使用NSIS内置页面或者定制界面,通过脚本可以指定页面的顺序、显示样子和行为。 Page指令用来定义安装程序中的页面,UninstPage用来定义,此外PageEx指令提供类是功能,但提供更多选项。页面的顺序和它在nsi脚本中出现的次序一致。
示例:
Page license
Page components
Page directory
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles
规定安装程序首先显示license页面,然后显示components选择页面,接着显示安装目录选择页面。
页面选项
不同的页面有不同的选项:
License page有LicenseText,LicenseData,LicenseForceSelection;
Components selection页面有ComponentText;
Directory selection页面有DirText,DirVar(仅能在PageEx中使用),DirVerify;
Un/Installation log页面有DetailsButtonText,CompletedText;
与时电脑知识库
Uninstall confirmation页面有DirVar(仅能在PageEx中使用),UninstallText
对于内置的Page,NSIS支持三个回调函数用于定制界面和验证,对于自定义页面NSIS支持两个回调函数。
Page指令语法
Page licensecomponentsdirectoryinstfilesuninstConfirm) [pre_function] [show_function] [leave_function]
或者:
Page custom [creator_function] [leave_function] [caption]
示例:
Page license skipLicense "" stayInLicense
Page custom customPage "" ": custom page"
Page instfiles
Function skipLicense
MessageBox MB_YESNO "Do you want to skip the license page?" IDNO no
Abort
no:
FunctionEnd
Function stayInLicense
MessageBox MB_YESNO "Do you want to stay in the license page?" IDNO no
Abort
no:
FunctionEnd
Function customPage
GetTempFileName $R0
File /oname=$R0 customPage.ini
InstallOptions::dialog $R0 与时(fortime.net)
Pop $R1
StrCmp $R1 "cancel" done
StrCmp $R1 "back" done
StrCmp $R1 "success" done
error: MessageBox MB_OKMB_ICONSTOP "InstallOptions error:$\r$\n$R1"
done:
FunctionEnd
UninstPage指令语法
UninstPage custom [creator_function] [leave_function] [caption]
OR
UninstPage (licensecomponentsdirectoryinstfilesuninstConfirm) [pre_function] [show_function] [leave_function]
PageEx语法
PageEx使用嵌套结构,比如:
PageEx license
LicenseText "Readme"
LicenseData readme.rtf
PageCallbacks licensePre licenseShow licenseLeave
PageExEnd
常用的nsi指令
nsi大致可以分为基本指令、注册表及ini操作指令、通用指令、流程控制指令、文件操作指令、卸载指令、字符串处理指令、多语言支持指令、重启指令。
以下是常用的基本指令:
Delete
Delete [/REBOOTOK] file
Exec
Exec command
ExecShell
ExecShell action command [parameters] [SW_SHOWNORMAL SW_SHOWMAXIMIZED SW_SHOWMINIMIZED SW_HIDE]ExecShell "open" 示例"http://nsis.sf.net/"
与时电脑知识库
ExecWait
ExecWait command [user_var(exit code)]
示例:
ExecWait '"$INSTDIR\someprogram.exe"'
ExecWait '"$INSTDIR\someprogram.exe"' $0
DetailPrint "some program returned $0"
File
File [/nonfatal] [/a] ([/r] [/x filewildcard [...]] (filewildcard) [...] /oname=file.dat infile.dat)
/r选项用作递归模式,/x用于排出文件
示例:
File something.exe
File /a something.exe
File *.exe
File /r *.dat
File /r data
File /oname=$TEMP\temp.dat somefile.ext
File /nonfatal "a file that might not exist"
File /r /x CVS myproject
File /r /x *.res /x *.obj /x *.pch source
Rename
Rename [/REBOOTOK] source_file dest_file
RMDir
RMDir [/r] [/REBOOTOK] directory_name
NSIS System 插件
(C) brainsucker (Nik Medved), 2002 与时电脑知识库
内容表
- 简介
- 有效函数
- 内存相关函数
- 调用函数
- 64 位函数
- FAQ
简介
System 插件给开发者提供了从外部 DLL 调用任何函数的功能。例如,你可以用它来调用 GetLogicalDriveStrings 来获取用户电脑里的驱动器列表。
fortime.net
System 插件也允许开发者来分配、释放、复制内存;与 COM 对象相配合并执行 64 位整数数学操作。
与时电脑知识库(fortime.net)
为了理解 System 插件强烈推荐首先有程序方面的知识。
与时电脑知识库(www.fortime.net)
档案里的一些使用例子
- Get local time
- Register conduits with Palm HotSync
- Get free memory
- Read REG_MULTI_SZ
- Get disk serial number
有效函数
内存相关函数
- Alloc SIZE
分配 SIZE 字节并返回一个内存地址到堆栈上。 与时电脑知识库
使用例子
System::Alloc 64 Pop $0 DetailPrint "64 字节分配在 $0" System::Free $0
与时电脑知识库(www.fortime.net)
- Copy [/SIZE] DESTINATION SOURCE
从 SOURCE 复制 SIZE 字节到 DESTINATION。如果不指定 SIZE,SOURCE 的大小必须使用 GlobalSize。这意味着如果你不使用 System::Alloc,System::Call 或 GlobalAllocCopies 来分配 SOURCE,你就必须指定 SIZE。
与时IT资讯(fortime.net)
使用例子
# 分配一个缓冲区并把‘测试字串'压入 System::Call "*(&t1024 '测试字串', i 5) i .s" Pop $0 # 复制到一个自动创建的缓冲区 System::Copy 0 $0 Pop $1 # 在 $1 缓冲区获取字串和整数 System::Call "*$1(&t1024 .r2, i .r3)" # 释放缓冲区 System::Free $1 # 输出结果 DetailPrint $2 DetailPrint $3 # 复制到我们自己的缓冲区 System::Alloc 1028 Pop $1 System::Copy $1 $0 # 在 $1 缓冲区获取字串和整数 System::Call "*$1(&t1024 .r2, i .r3)" # 释放 System::Free $0 System::Free $1 # 输出结果 DetailPrint $2 DetailPrint $3 与时IT资讯
- Free ADDRESS
释放ADDRESS. 与时电脑知识库(www.fortime.net)
使用例子
System::Alloc 64 Pop $0 DetailPrint "64 字节分配在 $0" System::Free $0 与时IT资讯(www.fortime.net)
- Store "OPERATION [OPERATION [OPERATION ...]]"
执行堆栈操作。一个操作可以从 NSIS 堆栈压入或弹出一个已注册的变量或者压入弹出所有系统已注册的变量 ($0 - $9 和 $R0 - $R9)。操作可以由任何字符分割。
与时电脑知识库
有效的操作
- 要压入 $#,使用 p#,# 是一个从 0 到 9 的数字。
- 要弹出 $#,使用 r#,# 是一个从 0 到 9 的数字。
- 要压入 $R#,使用 P#,# 是一个从 0 到 9 的数字。
- 要弹出 $R#,使用 R#,# 是一个从 0 到 9 的数字。
- 要压入 $0-$9 和 $R0-$R9 到系统私有的堆栈,使用 s 或 S。
- 要从系统私有的堆栈弹出 $0-$9 和 $R0-$R9 使用 l 或 L。
注意系统私有堆栈当 System 插件从 NSIS 卸载后将会丢失。如果你想使用它,你就必须保持 System 插件一直载入。你可以在你的脚本里使用 SetPluginUnload 或加 /NOUNLOAD 参数来使得插件不卸载。
与时电脑知识库(fortime.net)
使用例子
StrCpy $0 "test" System::Store "p0" Pop $1 DetailPrint "$0 = $1"
fortime.net
StrCpy $2 "test" System::Store "p2 R2" DetailPrint "$2 = $R2"
与时IT资讯
StrCpy $3 "test" System::Store /NOUNLOAD "s" StrCpy $3 "another test" System::Store "l" DetailPrint $3
与时电脑知识库(fortime.net)
System::Store "r4" "test" DetailPrint $4 与时(fortime.net)
调用函数
- Call PROC [( PARAMS ) [RETURN [? OPTIONS]]]
- Get PROC [( PARAMS ) [RETURN [? OPTIONS]]]
调用和获取都是共用一个语法。就如名称所述, Call 就是调用 Get 就是获取。它要调用什么或获取什么?由 PROC 的值决定。
与时电脑知识库(fortime.net)
PARAMS 是一个参数列表和要和他们做什么。你可以在参数里传递数据并且也可以从它们那里获取数据。这些参数列表由逗号分隔。每个参数由三个值组合而成: 类型、源、目标。类型可以是一个整数,一个字串,等等。源,就是参数值的源,可以是一个 NSIS 变量($0、$1、$INSTDIR),NSIS 堆栈,一个具体的值(5、"test",等等)或空(NULL)。目标,就是调用返回后的参数值,可以是 NSIS 变量,NSIS 堆栈或空(意味着该输出不需要)。如果不需要源或目标的话可以用一个句点表示(.)。 与时IT资讯(fortime.net)
RETURN 像一个单一参数的定义,但当创建回调函数时仅使用到源。通常源是一个句点。
与时电脑知识库(fortime.net)
OPTIONS 是一个 System 插件行为控制方法的选项列表。每一个选项可以由一个感叹号前缀关闭。例如: ?!e。
与时电脑知识库
PARAMS,RETURN 和 OPTIONS 在一个 Get/Call 行里可以重复多次。当重复时,可以省略很多,而只需要使用你需要改变的。类型,源 和/或目标可以省略每一个参数,即使返回值。选项可以添加或移除。这允许你来定义函数原型并保存为一些类型。最后的两个例子 作了演示。 与时电脑知识库(fortime.net)
PROC 也可以重复但必须带井号前缀(#)。 www.fortime.net
可能的 PROC 值和意义
值 意义 例子 DLL::FUNC DLL 输出的函数 user32::MessageBox ::ADDR 地址为 ADDR 的函数 看下面 *ADDR 地址为 ADDR 的结构 看下面 * 新结构 看下面 IPTR->IDX 成员索引 IDX 从界面由 IPTR 指向 看下面 <nothing> 新的回调函数 看下面 PROC 由 Get 返回的 PROC 看下面 有效的参数类型
类型 意义 v void (常用于返回) i int (包括 char、byte、short、句柄、指针 等) l 长整数、int64 t 文本,字串(指向第一个字符) w WCHAR 文本,Unicode 字串 g GUID k 回调 &vN N 字节填充 (仅结构) &iN N 字节整数 (仅结构) &l 结构大小 (仅结构) &tN N 字节文本 (仅结构) &wN N 字节 Unicode 文本 (仅结构) &gN N 字节 GUID (仅结构) 另外,每一种类型可以加一个星号表示指针。当使用一个星号时,System 插件仍然认为是参数的值,而不是指针地址。要传递直接的地址,使用没有星号的 i。一个使用例子。Alloc 返回地址并且它的返回值因此被用于 i,不带星号。
与时电脑知识库(www.fortime.net)
有效的源和目标
类型 意义 . 忽略 number 十六进制、十进制或八进制整数值。许多整数可以使用 来执行或操作。 'string'
"string"
`string`字串值 r0 到 r9 分别是 $0 到 $9 r10 到r19
R0 到R9分别是 $R0 到 $R9 c $CMDLINE d $INSTDIR o $OUTDIR e $EXEDIR a $LANG s NSIS 堆栈 n 空的源,目标不需要输出 回调
回调函数是一个被传递到一个函数并被它本身回调的简单的函数。它们常用于一项接一项传递一个可能的大量数据设置。例如: EnumChildWindows 使用一个回调函数。像 NSIS 函数不是完全正规的函数一样,System 插件提供它自己的机制来支持回调函数。它允许你来创建回调函数并当一个回调函数被调用时通知你。
与时IT资讯(www.fortime.net)
回调函数的创建使用 Get 和回调的语法。就像你不能调用回调本身一样,参数的源应该使用一个句点来忽略。当回调被调用时,目标参数将使用回调传递的参数来填充。回调将要返回的值由源返回参数设置。目标的返回参数应总是设为当 System 通知回调被调用时。
与时IT资讯
System::Get "(i .r0, i .r1) iss" 与时IT资讯(fortime.net)
要传递回调到一个函数,请使用 k 类型。
www.fortime.net
System::Get "(i .r0, i .r1) isR0" Pop $0 System::Call "dll::UseCallback(k r0)" 与时电脑知识库(fortime.net)
每次回调被调用时,字串 callback# (这里 # 代表回调的次数) 将会被在返回 “参数” 的目标里被替换,第一次创建的为 1,第二次为 2,第三次为 3 等等。就如 System 为单线程一样,回调也只能在调用另一个参数时被调用。例如,EnumChildWindows 的回调也只能在 EnumChildWindows 被调用时被调用。因此你应该在每次可能会调用回调的函数调用后检测 callback#。 与时IT资讯(fortime.net)
System::Call "(i .r0, i .r1) isR0" Pop $0 System::Call "dll::UseCallback(k r0)" StrCmp $R0 "callback1" 0 +2 DetailPrint "UseCallback passed ($0, $1) to the callback" www.fortime.net
在你处理回调的调用后,你应该使用 Call,把 Get - 回调 返回的值传给它。这将告诉 System 从回调里返回。如果当回调创建时为返回的参数指定了源,你应当把返回值赋给源。因为回调不能自动的释放,所以当你使用完之后不要忘了释放它。
与时(fortime.net)
SetPluginUnload alwaysoff System::Call "(i .r0, i .r1) isR0" Pop $0 System::Call "dll::UseCallback(k r0)" loop: StrCmp $R0 "callback1" 0 done DetailPrint "UseCallback passed ($0, $1) to the callback" Push 1 # return value of the callback System::Call $0 # tell system to return from the callback Goto loop done: SetPluginUnload manual System::Free $0 fortime.net
一个完整的例子。
与时IT资讯(fortime.net)
注意事项
- 要查找一个 COM 界面的成员索引,你需要查找 Visual C/C++ 或平台 SDK 里的 COM 界面头文件定义。记住索引从零开始。
- 记住当使用回调时记得使用 NSIS 的 /NOUNLOAD 开关或 SetPluginUnload。因为如果插件被卸载了它就不能被正常调用了。
- 如果找不到函数则会把一个 A 附加在函数名的后面,然后再次查找函数。这是因为许多的 Windows API 函数都有两个版本,一个是 ANSI 版本另一个是 Unicode 版本,ANSI 版本标记为 A 而 Unicode 版本标记为 W。例如: lstrcpyA 和 lstrcpyW。
有效的选项
选项 意义 c cdecl 调用约定 (堆栈由 caller 重建)。默认情况下使用 stdcall (堆栈由 callee重建)。 r 总是返回 (对于 GET 来说意味着你应该弹出结果并处理,对于 CALL 来说应该至少弹出结果)。默认情况下仅对错误返回 (对于 GET 来说你可以弹出错误结果和正确的处理,而对于 CALL 来说你将获得返回或定义的地方的结果)。 n 不重新定义。无论过程如何都不会用 GET 或 CALL 来重新定义。该选项不会继承到子项。 s 使用常规堆栈。对于函数调用无论何时第一次回调定义的系统都优先使用临时堆栈。 e 在程序结束后调用Call GetLastError() 并把结果压入堆栈。 u 调用后卸载 DLL (使用 FreeLibrary,使你可以删除它本身)。 使用例子
System::Call "user32::MessageBox(i $HWNDPARENT, t 'NSIS System Plug-in', t 'Test', i 0)" 与时IT资讯(www.fortime.net)
System::Call "kernel32::GetModuleHandle(t 'user32.dll') i .s" System::Call "kernel32::GetProcAddress(i s, t 'MessageBoxA') i .r0" System::Call "::$0(i $HWNDPARENT, t 'GetProcAddress test', t 'NSIS System Plug-in', i 0)" 与时IT资讯(www.fortime.net)
System::Get "user32::MessageBox(i $HWNDPARENT, t 'This is a default text', t 'Default', i 0)" Pop $0 System::Call "$0" 与时电脑知识库(www.fortime.net)
System::Get "user32::MessageBox(i $HWNDPARENT, t 'This is a default text', \ t 'Default', i 0x10x10)" Pop $0 System::Call "$0(, 'This is a System::Get test', 'NSIS System Plug-in',)"
与时IT资讯(fortime.net)
System::Call "advapi32::GetUserName(t .r0, *i ${NSIS_MAX_STRLEN} r1) i.r2" DetailPrint "User name - $0" DetailPrint "String length - $1" DetailPrint "Return value - $2" 与时电脑知识库(fortime.net)
System::Alloc 4 Pop $0 System::Call "*$0(i 5)" System::Call "*$0(i .r1)" DetailPrint $1
与时电脑知识库(fortime.net)
System::Call "*(i 5) i .r0" System::Call "*$0(i .r1)" DetailPrint $1
与时IT资讯(fortime.net)
# defines !define CLSCTX_INPROC_SERVER 1 !define CLSID_ActiveDesktop {75048700-EF1F-11D0-9888-006097DEACF9} !define IID_IActiveDesktop {F490EB00-1240-11D1-9888-006097DEACF9} # create IActiveDesktop interface System::Call "ole32::CoCreateInstance( \ g '${CLSID_ActiveDesktop}', i 0, \ i ${CLSCTX_INPROC_SERVER}, \ g '${IID_IActiveDesktop}', *i .r0) i.r1" StrCmp $1 0 0 end # call IActiveDesktop->GetWallpaper System::Call "$0->4(w .r2, i ${NSIS_MAX_STRLEN}, i 0)" # call IActiveDesktop->Release System::Call "$0->2()" # print result DetailPrint $2 end: 与时IT资讯(www.fortime.net)
InitPluginsDir SetOutPath $PLUGINSDIR File MyDLL.dll System::Call "MyDLL::MyFunc(i 5) ? u" Delete $PLUGINSDIR\MyDLL.dll 与时IT资讯(fortime.net)
SetPluginUnload alwaysoff System::Get "(i.r1, i) iss" Pop $R0 System::Call "user32::EnumChildWindows(i $HWNDPARENT, k R0, i) i.s" loop: Pop $0 StrCmp $0 "callback1" 0 done System::Call "user32::GetWindowText(ir1,t.r2,i${NSIS_MAX_STRLEN})" System::Call "user32::GetClassName(ir1,t.r3,i${NSIS_MAX_STRLEN})" IntFmt $1 "0x%X" $1 DetailPrint "$1 - [$3] $2" Push 1 # callback's return value System::Call "$R0" Goto loop done: SetPluginUnload manual System::Free $R0
www.fortime.net
!define MB "user32::MessageBox(i$HWNDPARENT,t,t'NSIS System Plug-in',i0)" System::Call "${MB}(,'my message',,)" System::Call "${MB}(,'another message',,) i.r0" MessageBox MB_OK "last call returned $0"
与时IT资讯
System::Call "user32::SendMessage(i $HWNDPARENT, t 'test', t 'test', i 0) i.s ? \ e (,t'test replacement',,) i.r0 ? !e #user32::MessageBox" DetailPrint $0 ClearErrors Pop $0 IfErrors good MessageBox MB_OK "this message box will never be reached" good:
与时IT资讯(www.fortime.net)
64 位函数
- Int64Op ARG1 OP [ARG2]
执行 ARG1 和选项 ARG2 之间的 OP 操作,返回值到堆栈顶。ARG1 和 ARG2 都是 64 位整数,这意味着它们可以处理从 -2^63 到 2^63 - 1 的整数。
fortime.net
有效的运算符
- 加法 -- +
- 减法 -- -
- 乘法 -- *
- 除法 -- /
- 取模 -- %
- 位或 --
- 位与 -- &
- 位异或 -- ^
- 逻辑或 --
- 逻辑与 -- &&
- 小于 -- <
- 大于 -- >
- 等于 -- =
- 位非 (单变量) -- ~
- 逻辑非 (单变量) -- !
使用例子
System::Int64Op 5 + 5 Pop $0 DetailPrint "5 + 5 = $0" # 10
与时电脑知识库(www.fortime.net)
System::Int64Op 64 - 25 Pop $0 DetailPrint "64 - 25 = $0" # 39 与时电脑知识库(www.fortime.net)
System::Int64Op 526355 * 1565487 Pop $0 DetailPrint "526355 * 1565487 = $0" # 824001909885 与时IT资讯
System::Int64Op 5498449498849818 / 3 Pop $0 DetailPrint "5498449498849818 / 3 = $0" # 1832816499616606
与时电脑知识库(www.fortime.net)
System::Int64Op 0x89498A198E4566C % 157 Pop $0 DetailPrint "0x89498A198E4566C % 157 = $0" # 118 与时IT资讯(www.fortime.net)
System::Int64Op 0xF0F0F0F 0xF0F0FFF Pop $0 # IntFmt is 32-bit, this is just for the example IntFmt $0 "0x%X" $0 DetailPrint "0xF0F0F0F 0xF0F0FFF = $0" # 0xF0F0FFF
与时电脑知识库(fortime.net)
System::Int64Op 0x12345678 & 0xF0F0F0F0 Pop $0 # IntFmt is 32-bit, this is just for the example IntFmt $0 "0x%X" $0 DetailPrint "0x12345678 & 0xF0F0F0F0 = $0" # 0x10305070
与时电脑知识库(www.fortime.net)
System::Int64Op 1 ^ 0 Pop $0 DetailPrint "1 ^ 0 = $0" # 1 与时(fortime.net)
System::Int64Op 1 0 Pop $0 DetailPrint "1 0 = $0" # 1 与时电脑知识库(www.fortime.net)
System::Int64Op 1 && 0 Pop $0 DetailPrint "1 && 0 = $0" # 0
与时(fortime.net)
System::Int64Op 9302157012375 < 570197509190760 Pop $0 DetailPrint "9302157012375 < 570197509190760 = $0" # 1
fortime.net
System::Int64Op 5168 > 89873 Pop $0 DetailPrint "5168 > 89873 = $0" # 0
与时IT资讯
System::Int64Op 189189 = 189189 Pop $0 DetailPrint "189189 = 189189 = $0" # 1
fortime.net
System::Int64Op 156545668489 ~ Pop $0 DetailPrint "1 ~ = $0" # -156545668490 与时IT资讯
System::Int64Op 1 ! Pop $0 DetailPrint "1 ! = $0" # 0 fortime.net
FAQ
- Q: 如何把一个结构传递到函数?
A: 首先,你必须先为结构分配内存。有两种方法: 使用 Alloc 或带有特殊结构分配语法的 Call。然后,如果你要在结构传递数据,你首先要把数据填入结构体。然后你才可以用一个指向结构的指针来调用函数。最后,调用函数后如果你想从结构体里取出数据,你必须使用带有结构指针的 Call。上面这些都做完了之后别忘了释放结构体。
与时电脑知识库(www.fortime.net)
分配内存
要分配内存给结构体请使用Alloc,但是你必须知道结构体的大小。当然你也可以用Call。在这个例子里可以很明显地看出这个结构体的大小是 16 字节,但是在其他的例子可能就不是这样子了。在所有的例子里,结构体的地址都被保存在堆栈顶部,你需要用 Pop 来把它弹出到变量。
与时电脑知识库(fortime.net)
System::Alloc 16 与时IT资讯(www.fortime.net)
System::Call "*(i, i, i, t)i.s" 与时电脑知识库
设置数据
写入数据可以使用Call。可以在分配内存时就进行,或者用其它方法分配后使用带结构指针的语法。
与时电脑知识库(www.fortime.net)
System::Call "*(i 5, i 2, i 513, t 'test')i.s"
与时IT资讯
# 假设结构体的内存地址保存在 $0 里 System::Call "*$0(i 5, i 2, i 513, t 'test')"
与时电脑知识库
把结构体传递到函数
就像一些分配方法返回一个地址一样,这里要传递的数据类型应该是一个整数 - 一个保存了结构体地址的整数。 与时电脑知识库(fortime.net)
# 假设结构体的内存地址保存在 $0 里 System::Call "dll::func(i r0)" 与时电脑知识库(fortime.net)
读取数据
读取数据可以使用和写入数据相同的语法。说不同的是要有输出变量而输入部分用一个句点来表示。 与时电脑知识库(fortime.net)
# 假设结构体的内存地址保存在 $0 里 System::Call "*$0(i .r0, i .r1, i .r2, t .r3)" DetailPrint "第一个整数 = $0" DetailPrint "第二个整数 = $1" DetailPrint "第三个整数 = $2" DetailPrint "字串 = $3"
与时(fortime.net)
释放内存
使用Free 来释放内存。 与时IT资讯
# 假设结构体的内存地址保存在 $0 里 System::Free $0
与时IT资讯(fortime.net)
NSIS安装程序制件软件 下载地址:http://www.wishdown.com/Software/Catalog139/10926.html
福利游戏
相关文章
更多精选合集
更多大家都在玩
大家都在看
更多-
- 原神5.2版本有什么福利
- 时间:2024-11-21
-
- 无限暖暖谈幽幽最新过关技巧
- 时间:2024-11-21
-
- 伊甸之战新手少走弯路技巧总汇一览
- 时间:2024-11-21
-
- 伊甸之战卡包获得方法一览
- 时间:2024-11-21
-
- 伊甸之战战术研究馆打法技巧一览
- 时间:2024-11-21
-
- 伊甸之战肉身之转化过关攻略一览
- 时间:2024-11-21
-
- 伊甸之战战术研究馆玩法一览
- 时间:2024-11-21
-
- 伊甸之战兽族简单打法攻略一览
- 时间:2024-11-21