最新消息:

NSIS 插件开发 规范

nsis 永恒心锁 4640浏览 0评论

NSIS 插件开发 规范

1

NSIS 作为一 个安装程序制作工具,其本身的功能有限,而官方开放了插件开发的接口 ,因而可以编写 DLL 来增强
安装包的功能。从 NSIS 2.x 开始,插件的使用变得非常简单。在脚本中可以直接使用 DLL::func 这样的格式(其
中 DLL 代表插件 dll 的文件名, func 代表导出函数名 ,下同 )来调用插件命令,编译器即可自动将 DLL 打包,并
释放到临时的插查 $PLUGINSDIR ,系 。当安装包 关闭后 ,插件目录 中 会被自动删 $PLUGINSDIR 通
常是在临时文件夹下随机生成的文件夹。当执行到插件命令时,该文件夹将会创建。如果还没有调用插件命令,而
要 先 使用此文件夹 来释放 图片 资源等 ,可以使用 InitPluginsDir 来创建此文件夹。

NSIS 插件为 DLL 文件 ,所有函数必须为 C 风格导出函数 (但并不限于使用 C/C++ 开发插件, Delphi 、 Win32 ASM
也是可以的), 调用约定必须为 “ __cdecl ” 。例如导出函数 myFunction ,其 C 风格的 函数原型如下 :

#ifdef __cplusplus
 extern "C"
 #endif
 __declspec(dllexport) void __cdecl myFunction(
 HWND hwndParent,
 int string_size,
 TCHAR *variables,
 stack_t **stacktop,
 extra_parameters *extra
 );
 #ifdef __cplusplus
 }
 #endif

 第一个参数 hwndParent 代表 NSIS 的主窗口句柄。 NSIS 脚本中使用常变量 $HWNDPARENT 来引用窗口句柄值。
为什么叫它常变量? NSIS 中的常量是以“ $ ”开头的,且以花括号(大括号)包围的合法变量名,如 ${NSISDIR} 。
常量只存在于编译时期,等同于 C 语言的宏,且两者都是通过类似的语法来定义, NSIS 使用 !define ,而 C/C++
使用 #define 。 NSIS 脚本中的变量也是以“ $ ”开头的,但之后直接为合法变量名,并没有花括号,且变量是在运
行期间可以被更改赋值的。窗口句柄看起来像个变量,因为值却只有运行的时候才能得到,所以依然使用了变量的
表示方法。但其的值又 是不允许改变的,所以又符合常量的特征。这如同 C 语言里的 const 限定符,即这些常变量
通常是编译器限定不允许修改的,如 $EXEPATH 、 $EXEFILE 都属于常变量。实际上,通过插件仍可以修改这些所谓
的常量。这就是为什么帮助文档中说:从技术上来说你可以更改这个变量,但这并不是一个好主意。在 .onInit 函
数中该变量值为 0 ,因为此时窗口尚未创建,从 .onGUIInit 开始才有效。 在 .onGUIInit 函数中,我们可以通过
GetDlgItem 来获取主窗口上的按钮句柄。比如,上一步、下一步、取消等按钮 :

GetDlgItem $R0 $HWNDPARENT 1
 EnableWindow $R0 0

以便控制它们。如果要控制当前页面 (子窗口) 上的控件,我们要先 查找当前页面对话框的窗口句柄, 其 NSIS 脚
本 语法 为:

FindWindow $R0 "#32770" "" $HWNDPARENT

而如果在插件中,我们查找子窗口句柄,可以使用下面的 C/C++ 代码:

HWND hwndDialog = FindWindowEx(hwndParent, NULL, WC_DIALOG, NULL);

其中 WC_DIALOG 亦可使用 TEXT(“#32770”) 代替。至于这里为何是 32770 而不是其他数值,这个是微软规定的,
没有什么原因。 得到子窗口句柄之后,就 可以通过 GetDlgItem 来获取子窗口上的控件句柄,来控制当前页面的某
些控件,方法和获得父窗口上的控件句柄一致。

 第二个参数 string_size 代表 NSIS 的变量长度。这个概念可能有些人不懂了,变量还有长度?实际上, NSIS
脚本中, 变量 是没有 数据 类型的,他们都是统一长度的字符串类型, 并且所有的 变量都是等长的, 变量的地址 也 是
连续的 。 至于各个变量是如何存储的,将在下一个参数说明中介 绍 。 官方标准版本中变量的长度预定 为 1024
容纳 1023 个英文字符或 511 个中文字符。这个中文字符长度是针对 ANSI 版, Unicode 版则可以容纳 1023 个中
英 文字符。官方也 提供 8192 字节的版本 ,可根据需要选择。 你也可以自行编译 NSIS 来修改这个长度为其他数值,
最好是 4 的整倍数 。在 NSIS 源码中,它是通过宏 NSIS_MAX_STRLEN 来定义的。而在脚本中,它被 编译器预定义
为个译期常 ${NSIS_MAX_STRLEN} 。 虽是量但其用定常的别 该量值法
过 !undef 和 !define 进行改变。

 第三个参数 variables 代表 NSIS 中内部变量的首地址。 上面提到, NSIS 中所有的变量都是等长的,且在内

NSIS 插件开发 规范

1

NSIS 作为一 个安装程序制作工具,其本身的功能有限,而官方开放了插件开发的接口 ,因而可以编写 DLL 来增强
安装包的功能。从 NSIS 2.x 开始,插件的使用变得非常简单。在脚本中可以直接使用 DLL::func 这样的格式(其
中 DLL 代表插件 dll 的文件名, func 代表导出函数名 ,下同 )来调用插件命令,编译器即可自动将 DLL 打包,并
释放到临时的插查 $PLUGINSDIR ,系 。当安装包 关闭后 ,插件目录 中 会被自动删 $PLUGINSDIR 通
常是在临时文件夹下随机生成的文件夹。当执行到插件命令时,该文件夹将会创建。如果还没有调用插件命令,而
要 先 使用此文件夹 来释放 图片 资源等 ,可以使用 InitPluginsDir 来创建此文件夹。

NSIS 插件为 DLL 文件 ,所有函数必须为 C 风格导出函数 (但并不限于使用 C/C++ 开发插件, Delphi 、 Win32 ASM
也是可以的), 调用约定必须为 “ __cdecl ” 。例如导出函数 myFunction ,其 C 风格的 函数原型如下 :

#ifdef __cplusplus
 extern "C"
 #endif
 __declspec(dllexport) void __cdecl myFunction(
 HWND hwndParent,
 int string_size,
 TCHAR *variables,
 stack_t **stacktop,
 extra_parameters *extra
 );
 #ifdef __cplusplus
 }
 #endif

 第一个参数 hwndParent 代表 NSIS 的主窗口句柄。 NSIS 脚本中使用常变量 $HWNDPARENT 来引用窗口句柄值。
为什么叫它常变量? NSIS 中的常量是以“ $ ”开头的,且以花括号(大括号)包围的合法变量名,如 ${NSISDIR} 。
常量只存在于编译时期,等同于 C 语言的宏,且两者都是通过类似的语法来定义, NSIS 使用 !define ,而 C/C++
使用 #define 。 NSIS 脚本中的变量也是以“ $ ”开头的,但之后直接为合法变量名,并没有花括号,且变量是在运
行期间可以被更改赋值的。窗口句柄看起来像个变量,因为值却只有运行的时候才能得到,所以依然使用了变量的
表示方法。但其的值又 是不允许改变的,所以又符合常量的特征。这如同 C 语言里的 const 限定符,即这些常变量
通常是编译器限定不允许修改的,如 $EXEPATH 、 $EXEFILE 都属于常变量。实际上,通过插件仍可以修改这些所谓
的常量。这就是为什么帮助文档中说:从技术上来说你可以更改这个变量,但这并不是一个好主意。在 .onInit 函
数中该变量值为 0 ,因为此时窗口尚未创建,从 .onGUIInit 开始才有效。 在 .onGUIInit 函数中,我们可以通过
GetDlgItem 来获取主窗口上的按钮句柄。比如,上一步、下一步、取消等按钮 :

GetDlgItem $R0 $HWNDPARENT 1
 EnableWindow $R0 0

以便控制它们。如果要控制当前页面 (子窗口) 上的控件,我们要先 查找当前页面对话框的窗口句柄, 其 NSIS 脚
本 语法 为:

FindWindow $R0 "#32770" "" $HWNDPARENT

而如果在插件中,我们查找子窗口句柄,可以使用下面的 C/C++ 代码:

HWND hwndDialog = FindWindowEx(hwndParent, NULL, WC_DIALOG, NULL);

其中 WC_DIALOG 亦可使用 TEXT(“#32770”) 代替。至于这里为何是 32770 而不是其他数值,这个是微软规定的,
没有什么原因。 得到子窗口句柄之后,就 可以通过 GetDlgItem 来获取子窗口上的控件句柄,来控制当前页面的某
些控件,方法和获得父窗口上的控件句柄一致。

 第二个参数 string_size 代表 NSIS 的变量长度。这个概念可能有些人不懂了,变量还有长度?实际上, NSIS
脚本中, 变量 是没有 数据 类型的,他们都是统一长度的字符串类型, 并且所有的 变量都是等长的, 变量的地址 也 是
连续的 。 至于各个变量是如何存储的,将在下一个参数说明中介 绍 。 官方标准版本中变量的长度预定 为 1024
容纳 1023 个英文字符或 511 个中文字符。这个中文字符长度是针对 ANSI 版, Unicode 版则可以容纳 1023 个中
英 文字符。官方也 提供 8192 字节的版本 ,可根据需要选择。 你也可以自行编译 NSIS 来修改这个长度为其他数值,
最好是 4 的整倍数 。在 NSIS 源码中,它是通过宏 NSIS_MAX_STRLEN 来定义的。而在脚本中,它被 编译器预定义
为个译期常 ${NSIS_MAX_STRLEN} 。 虽是量但其用定常的别 该量值法
过 !undef 和 !define 进行改变。

 第三个参数 variables 代表 NSIS 中内部变量的首地址。 上面提到, NSIS 中所有的变量都是等长的,且在内

NSIS 插件开发 规范

1

NSIS 作为一 个安装程序制作工具,其本身的功能有限,而官方开放了插件开发的接口 ,因而可以编写 DLL 来增强
安装包的功能。从 NSIS 2.x 开始,插件的使用变得非常简单。在脚本中可以直接使用 DLL::func 这样的格式(其
中 DLL 代表插件 dll 的文件名, func 代表导出函数名 ,下同 )来调用插件命令,编译器即可自动将 DLL 打包,并
释放到临时的插查 $PLUGINSDIR ,系 。当安装包 关闭后 ,插件目录 中 会被自动删 $PLUGINSDIR 通
常是在临时文件夹下随机生成的文件夹。当执行到插件命令时,该文件夹将会创建。如果还没有调用插件命令,而
要 先 使用此文件夹 来释放 图片 资源等 ,可以使用 InitPluginsDir 来创建此文件夹。

NSIS 插件为 DLL 文件 ,所有函数必须为 C 风格导出函数 (但并不限于使用 C/C++ 开发插件, Delphi 、 Win32 ASM
也是可以的), 调用约定必须为 “ __cdecl ” 。例如导出函数 myFunction ,其 C 风格的 函数原型如下 :

#ifdef __cplusplus
 extern "C"
 #endif
 __declspec(dllexport) void __cdecl myFunction(
 HWND hwndParent,
 int string_size,
 TCHAR *variables,
 stack_t **stacktop,
 extra_parameters *extra
 );
 #ifdef __cplusplus
 }
 #endif

 第一个参数 hwndParent 代表 NSIS 的主窗口句柄。 NSIS 脚本中使用常变量 $HWNDPARENT 来引用窗口句柄值。
为什么叫它常变量? NSIS 中的常量是以“ $ ”开头的,且以花括号(大括号)包围的合法变量名,如 ${NSISDIR} 。
常量只存在于编译时期,等同于 C 语言的宏,且两者都是通过类似的语法来定义, NSIS 使用 !define ,而 C/C++
使用 #define 。 NSIS 脚本中的变量也是以“ $ ”开头的,但之后直接为合法变量名,并没有花括号,且变量是在运
行期间可以被更改赋值的。窗口句柄看起来像个变量,因为值却只有运行的时候才能得到,所以依然使用了变量的
表示方法。但其的值又 是不允许改变的,所以又符合常量的特征。这如同 C 语言里的 const 限定符,即这些常变量
通常是编译器限定不允许修改的,如 $EXEPATH 、 $EXEFILE 都属于常变量。实际上,通过插件仍可以修改这些所谓
的常量。这就是为什么帮助文档中说:从技术上来说你可以更改这个变量,但这并不是一个好主意。在 .onInit 函
数中该变量值为 0 ,因为此时窗口尚未创建,从 .onGUIInit 开始才有效。 在 .onGUIInit 函数中,我们可以通过
GetDlgItem 来获取主窗口上的按钮句柄。比如,上一步、下一步、取消等按钮 :

GetDlgItem $R0 $HWNDPARENT 1
 EnableWindow $R0 0

以便控制它们。如果要控制当前页面 (子窗口) 上的控件,我们要先 查找当前页面对话框的窗口句柄, 其 NSIS 脚
本 语法 为:

FindWindow $R0 "#32770" "" $HWNDPARENT

而如果在插件中,我们查找子窗口句柄,可以使用下面的 C/C++ 代码:

HWND hwndDialog = FindWindowEx(hwndParent, NULL, WC_DIALOG, NULL);

其中 WC_DIALOG 亦可使用 TEXT(“#32770”) 代替。至于这里为何是 32770 而不是其他数值,这个是微软规定的,
没有什么原因。 得到子窗口句柄之后,就 可以通过 GetDlgItem 来获取子窗口上的控件句柄,来控制当前页面的某
些控件,方法和获得父窗口上的控件句柄一致。

 第二个参数 string_size 代表 NSIS 的变量长度。这个概念可能有些人不懂了,变量还有长度?实际上, NSIS
脚本中, 变量 是没有 数据 类型的,他们都是统一长度的字符串类型, 并且所有的 变量都是等长的, 变量的地址 也 是
连续的 。 至于各个变量是如何存储的,将在下一个参数说明中介 绍 。 官方标准版本中变量的长度预定 为 1024
容纳 1023 个英文字符或 511 个中文字符。这个中文字符长度是针对 ANSI 版, Unicode 版则可以容纳 1023 个中
英 文字符。官方也 提供 8192 字节的版本 ,可根据需要选择。 你也可以自行编译 NSIS 来修改这个长度为其他数值,
最好是 4 的整倍数 。在 NSIS 源码中,它是通过宏 NSIS_MAX_STRLEN 来定义的。而在脚本中,它被 编译器预定义
为个译期常 ${NSIS_MAX_STRLEN} 。 虽是量但其用定常的别 该量值法
过 !undef 和 !define 进行改变。

 第三个参数 variables 代表 NSIS 中内部变量的首地址。 上面提到, NSIS 中所有的变量都是等长的,且在内

NSIS 插件开发 规范

1

NSIS 作为一 个安装程序制作工具,其本身的功能有限,而官方开放了插件开发的接口 ,因而可以编写 DLL 来增强
安装包的功能。从 NSIS 2.x 开始,插件的使用变得非常简单。在脚本中可以直接使用 DLL::func 这样的格式(其
中 DLL 代表插件 dll 的文件名, func 代表导出函数名 ,下同 )来调用插件命令,编译器即可自动将 DLL 打包,并
释放到临时的插查 $PLUGINSDIR ,系 。当安装包 关闭后 ,插件目录 中 会被自动删 $PLUGINSDIR 通
常是在临时文件夹下随机生成的文件夹。当执行到插件命令时,该文件夹将会创建。如果还没有调用插件命令,而
要 先 使用此文件夹 来释放 图片 资源等 ,可以使用 InitPluginsDir 来创建此文件夹。

NSIS 插件为 DLL 文件 ,所有函数必须为 C 风格导出函数 (但并不限于使用 C/C++ 开发插件, Delphi 、 Win32 ASM
也是可以的), 调用约定必须为 “ __cdecl ” 。例如导出函数 myFunction ,其 C 风格的 函数原型如下 :

#ifdef __cplusplus
 extern "C"
 #endif
 __declspec(dllexport) void __cdecl myFunction(
 HWND hwndParent,
 int string_size,
 TCHAR *variables,
 stack_t **stacktop,
 extra_parameters *extra
 );
 #ifdef __cplusplus
 }
 #endif

 第一个参数 hwndParent 代表 NSIS 的主窗口句柄。 NSIS 脚本中使用常变量 $HWNDPARENT 来引用窗口句柄值。
为什么叫它常变量? NSIS 中的常量是以“ $ ”开头的,且以花括号(大括号)包围的合法变量名,如 ${NSISDIR} 。
常量只存在于编译时期,等同于 C 语言的宏,且两者都是通过类似的语法来定义, NSIS 使用 !define ,而 C/C++
使用 #define 。 NSIS 脚本中的变量也是以“ $ ”开头的,但之后直接为合法变量名,并没有花括号,且变量是在运
行期间可以被更改赋值的。窗口句柄看起来像个变量,因为值却只有运行的时候才能得到,所以依然使用了变量的
表示方法。但其的值又 是不允许改变的,所以又符合常量的特征。这如同 C 语言里的 const 限定符,即这些常变量
通常是编译器限定不允许修改的,如 $EXEPATH 、 $EXEFILE 都属于常变量。实际上,通过插件仍可以修改这些所谓
的常量。这就是为什么帮助文档中说:从技术上来说你可以更改这个变量,但这并不是一个好主意。在 .onInit 函
数中该变量值为 0 ,因为此时窗口尚未创建,从 .onGUIInit 开始才有效。 在 .onGUIInit 函数中,我们可以通过
GetDlgItem 来获取主窗口上的按钮句柄。比如,上一步、下一步、取消等按钮 :

GetDlgItem $R0 $HWNDPARENT 1
 EnableWindow $R0 0

以便控制它们。如果要控制当前页面 (子窗口) 上的控件,我们要先 查找当前页面对话框的窗口句柄, 其 NSIS 脚
本 语法 为:

FindWindow $R0 "#32770" "" $HWNDPARENT

而如果在插件中,我们查找子窗口句柄,可以使用下面的 C/C++ 代码:

HWND hwndDialog = FindWindowEx(hwndParent, NULL, WC_DIALOG, NULL);

其中 WC_DIALOG 亦可使用 TEXT(“#32770”) 代替。至于这里为何是 32770 而不是其他数值,这个是微软规定的,
没有什么原因。 得到子窗口句柄之后,就 可以通过 GetDlgItem 来获取子窗口上的控件句柄,来控制当前页面的某
些控件,方法和获得父窗口上的控件句柄一致。

 第二个参数 string_size 代表 NSIS 的变量长度。这个概念可能有些人不懂了,变量还有长度?实际上, NSIS
脚本中, 变量 是没有 数据 类型的,他们都是统一长度的字符串类型, 并且所有的 变量都是等长的, 变量的地址 也 是
连续的 。 至于各个变量是如何存储的,将在下一个参数说明中介 绍 。 官方标准版本中变量的长度预定 为 1024
容纳 1023 个英文字符或 511 个中文字符。这个中文字符长度是针对 ANSI 版, Unicode 版则可以容纳 1023 个中
英 文字符。官方也 提供 8192 字节的版本 ,可根据需要选择。 你也可以自行编译 NSIS 来修改这个长度为其他数值,
最好是 4 的整倍数 。在 NSIS 源码中,它是通过宏 NSIS_MAX_STRLEN 来定义的。而在脚本中,它被 编译器预定义
为个译期常 ${NSIS_MAX_STRLEN} 。 虽是量但其用定常的别 该量值法
过 !undef 和 !define 进行改变。

 第三个参数 variables 代表 NSIS 中内部变量的首地址。 上面提到, NSIS 中所有的变量都是等长的,且在内

NSIS 插件开发 规范

1

NSIS 作为一 个安装程序制作工具,其本身的功能有限,而官方开放了插件开发的接口 ,因而可以编写 DLL 来增强
安装包的功能。从 NSIS 2.x 开始,插件的使用变得非常简单。在脚本中可以直接使用 DLL::func 这样的格式(其
中 DLL 代表插件 dll 的文件名, func 代表导出函数名 ,下同 )来调用插件命令,编译器即可自动将 DLL 打包,并
释放到临时的插查 $PLUGINSDIR ,系 。当安装包 关闭后 ,插件目录 中 会被自动删 $PLUGINSDIR 通
常是在临时文件夹下随机生成的文件夹。当执行到插件命令时,该文件夹将会创建。如果还没有调用插件命令,而
要 先 使用此文件夹 来释放 图片 资源等 ,可以使用 InitPluginsDir 来创建此文件夹。

NSIS 插件为 DLL 文件 ,所有函数必须为 C 风格导出函数 (但并不限于使用 C/C++ 开发插件, Delphi 、 Win32 ASM
也是可以的), 调用约定必须为 “ __cdecl ” 。例如导出函数 myFunction ,其 C 风格的 函数原型如下 :

#ifdef __cplusplus
 extern "C"
 #endif
 __declspec(dllexport) void __cdecl myFunction(
 HWND hwndParent,
 int string_size,
 TCHAR *variables,
 stack_t **stacktop,
 extra_parameters *extra
 );
 #ifdef __cplusplus
 }
 #endif

 第一个参数 hwndParent 代表 NSIS 的主窗口句柄。 NSIS 脚本中使用常变量 $HWNDPARENT 来引用窗口句柄值。
为什么叫它常变量? NSIS 中的常量是以“ $ ”开头的,且以花括号(大括号)包围的合法变量名,如 ${NSISDIR} 。
常量只存在于编译时期,等同于 C 语言的宏,且两者都是通过类似的语法来定义, NSIS 使用 !define ,而 C/C++
使用 #define 。 NSIS 脚本中的变量也是以“ $ ”开头的,但之后直接为合法变量名,并没有花括号,且变量是在运
行期间可以被更改赋值的。窗口句柄看起来像个变量,因为值却只有运行的时候才能得到,所以依然使用了变量的
表示方法。但其的值又 是不允许改变的,所以又符合常量的特征。这如同 C 语言里的 const 限定符,即这些常变量
通常是编译器限定不允许修改的,如 $EXEPATH 、 $EXEFILE 都属于常变量。实际上,通过插件仍可以修改这些所谓
的常量。这就是为什么帮助文档中说:从技术上来说你可以更改这个变量,但这并不是一个好主意。在 .onInit 函
数中该变量值为 0 ,因为此时窗口尚未创建,从 .onGUIInit 开始才有效。 在 .onGUIInit 函数中,我们可以通过
GetDlgItem 来获取主窗口上的按钮句柄。比如,上一步、下一步、取消等按钮 :

GetDlgItem $R0 $HWNDPARENT 1
 EnableWindow $R0 0

以便控制它们。如果要控制当前页面 (子窗口) 上的控件,我们要先 查找当前页面对话框的窗口句柄, 其 NSIS 脚
本 语法 为:

FindWindow $R0 "#32770" "" $HWNDPARENT

而如果在插件中,我们查找子窗口句柄,可以使用下面的 C/C++ 代码:

HWND hwndDialog = FindWindowEx(hwndParent, NULL, WC_DIALOG, NULL);

其中 WC_DIALOG 亦可使用 TEXT(“#32770”) 代替。至于这里为何是 32770 而不是其他数值,这个是微软规定的,
没有什么原因。 得到子窗口句柄之后,就 可以通过 GetDlgItem 来获取子窗口上的控件句柄,来控制当前页面的某
些控件,方法和获得父窗口上的控件句柄一致。

 第二个参数 string_size 代表 NSIS 的变量长度。这个概念可能有些人不懂了,变量还有长度?实际上, NSIS
脚本中, 变量 是没有 数据 类型的,他们都是统一长度的字符串类型, 并且所有的 变量都是等长的, 变量的地址 也 是
连续的 。 至于各个变量是如何存储的,将在下一个参数说明中介 绍 。 官方标准版本中变量的长度预定 为 1024
容纳 1023 个英文字符或 511 个中文字符。这个中文字符长度是针对 ANSI 版, Unicode 版则可以容纳 1023 个中
英 文字符。官方也 提供 8192 字节的版本 ,可根据需要选择。 你也可以自行编译 NSIS 来修改这个长度为其他数值,
最好是 4 的整倍数 。在 NSIS 源码中,它是通过宏 NSIS_MAX_STRLEN 来定义的。而在脚本中,它被 编译器预定义
为个译期常 ${NSIS_MAX_STRLEN} 。 虽是量但其用定常的别 该量值法
过 !undef 和 !define 进行改变。

 第三个参数 variables 代表 NSIS 中内部变量的首地址。 上面提到, NSIS 中所有的变量都是等长的,且在内

NSIS 插件开发 规范

1

NSIS 作为一 个安装程序制作工具,其本身的功能有限,而官方开放了插件开发的接口 ,因而可以编写 DLL 来增强
安装包的功能。从 NSIS 2.x 开始,插件的使用变得非常简单。在脚本中可以直接使用 DLL::func 这样的格式(其
中 DLL 代表插件 dll 的文件名, func 代表导出函数名 ,下同 )来调用插件命令,编译器即可自动将 DLL 打包,并
释放到临时的插查 $PLUGINSDIR ,系 。当安装包 关闭后 ,插件目录 中 会被自动删 $PLUGINSDIR 通
常是在临时文件夹下随机生成的文件夹。当执行到插件命令时,该文件夹将会创建。如果还没有调用插件命令,而
要 先 使用此文件夹 来释放 图片 资源等 ,可以使用 InitPluginsDir 来创建此文件夹。

NSIS 插件为 DLL 文件 ,所有函数必须为 C 风格导出函数 (但并不限于使用 C/C++ 开发插件, Delphi 、 Win32 ASM
也是可以的), 调用约定必须为 “ __cdecl ” 。例如导出函数 myFunction ,其 C 风格的 函数原型如下 :

#ifdef __cplusplus
 extern "C"
 #endif
 __declspec(dllexport) void __cdecl myFunction(
 HWND hwndParent,
 int string_size,
 TCHAR *variables,
 stack_t **stacktop,
 extra_parameters *extra
 );
 #ifdef __cplusplus
 }
 #endif

 第一个参数 hwndParent 代表 NSIS 的主窗口句柄。 NSIS 脚本中使用常变量 $HWNDPARENT 来引用窗口句柄值。
为什么叫它常变量? NSIS 中的常量是以“ $ ”开头的,且以花括号(大括号)包围的合法变量名,如 ${NSISDIR} 。
常量只存在于编译时期,等同于 C 语言的宏,且两者都是通过类似的语法来定义, NSIS 使用 !define ,而 C/C++
使用 #define 。 NSIS 脚本中的变量也是以“ $ ”开头的,但之后直接为合法变量名,并没有花括号,且变量是在运
行期间可以被更改赋值的。窗口句柄看起来像个变量,因为值却只有运行的时候才能得到,所以依然使用了变量的
表示方法。但其的值又 是不允许改变的,所以又符合常量的特征。这如同 C 语言里的 const 限定符,即这些常变量
通常是编译器限定不允许修改的,如 $EXEPATH 、 $EXEFILE 都属于常变量。实际上,通过插件仍可以修改这些所谓
的常量。这就是为什么帮助文档中说:从技术上来说你可以更改这个变量,但这并不是一个好主意。在 .onInit 函
数中该变量值为 0 ,因为此时窗口尚未创建,从 .onGUIInit 开始才有效。 在 .onGUIInit 函数中,我们可以通过
GetDlgItem 来获取主窗口上的按钮句柄。比如,上一步、下一步、取消等按钮 :

GetDlgItem $R0 $HWNDPARENT 1
 EnableWindow $R0 0

以便控制它们。如果要控制当前页面 (子窗口) 上的控件,我们要先 查找当前页面对话框的窗口句柄, 其 NSIS 脚
本 语法 为:

FindWindow $R0 "#32770" "" $HWNDPARENT

而如果在插件中,我们查找子窗口句柄,可以使用下面的 C/C++ 代码:

HWND hwndDialog = FindWindowEx(hwndParent, NULL, WC_DIALOG, NULL);

其中 WC_DIALOG 亦可使用 TEXT(“#32770”) 代替。至于这里为何是 32770 而不是其他数值,这个是微软规定的,
没有什么原因。 得到子窗口句柄之后,就 可以通过 GetDlgItem 来获取子窗口上的控件句柄,来控制当前页面的某
些控件,方法和获得父窗口上的控件句柄一致。

 第二个参数 string_size 代表 NSIS 的变量长度。这个概念可能有些人不懂了,变量还有长度?实际上, NSIS
脚本中, 变量 是没有 数据 类型的,他们都是统一长度的字符串类型, 并且所有的 变量都是等长的, 变量的地址 也 是
连续的 。 至于各个变量是如何存储的,将在下一个参数说明中介 绍 。 官方标准版本中变量的长度预定 为 1024
容纳 1023 个英文字符或 511 个中文字符。这个中文字符长度是针对 ANSI 版, Unicode 版则可以容纳 1023 个中
英 文字符。官方也 提供 8192 字节的版本 ,可根据需要选择。 你也可以自行编译 NSIS 来修改这个长度为其他数值,
最好是 4 的整倍数 。在 NSIS 源码中,它是通过宏 NSIS_MAX_STRLEN 来定义的。而在脚本中,它被 编译器预定义
为个译期常 ${NSIS_MAX_STRLEN} 。 虽是量但其用定常的别 该量值法
过 !undef 和 !define 进行改变。

 第三个参数 variables 代表 NSIS 中内部变量的首地址。 上面提到, NSIS 中所有的变量都是等长的,且在内

NSIS 插件开发 规范

1

NSIS 作为一 个安装程序制作工具,其本身的功能有限,而官方开放了插件开发的接口 ,因而可以编写 DLL 来增强
安装包的功能。从 NSIS 2.x 开始,插件的使用变得非常简单。在脚本中可以直接使用 DLL::func 这样的格式(其
中 DLL 代表插件 dll 的文件名, func 代表导出函数名 ,下同 )来调用插件命令,编译器即可自动将 DLL 打包,并
释放到临时的插查 $PLUGINSDIR ,系 。当安装包 关闭后 ,插件目录 中 会被自动删 $PLUGINSDIR 通
常是在临时文件夹下随机生成的文件夹。当执行到插件命令时,该文件夹将会创建。如果还没有调用插件命令,而
要 先 使用此文件夹 来释放 图片 资源等 ,可以使用 InitPluginsDir 来创建此文件夹。

NSIS 插件为 DLL 文件 ,所有函数必须为 C 风格导出函数 (但并不限于使用 C/C++ 开发插件, Delphi 、 Win32 ASM
也是可以的), 调用约定必须为 “ __cdecl ” 。例如导出函数 myFunction ,其 C 风格的 函数原型如下 :

#ifdef __cplusplus
 extern "C"
 #endif
 __declspec(dllexport) void __cdecl myFunction(
 HWND hwndParent,
 int string_size,
 TCHAR *variables,
 stack_t **stacktop,
 extra_parameters *extra
 );
 #ifdef __cplusplus
 }
 #endif

 第一个参数 hwndParent 代表 NSIS 的主窗口句柄。 NSIS 脚本中使用常变量 $HWNDPARENT 来引用窗口句柄值。
为什么叫它常变量? NSIS 中的常量是以“ $ ”开头的,且以花括号(大括号)包围的合法变量名,如 ${NSISDIR} 。
常量只存在于编译时期,等同于 C 语言的宏,且两者都是通过类似的语法来定义, NSIS 使用 !define ,而 C/C++
使用 #define 。 NSIS 脚本中的变量也是以“ $ ”开头的,但之后直接为合法变量名,并没有花括号,且变量是在运
行期间可以被更改赋值的。窗口句柄看起来像个变量,因为值却只有运行的时候才能得到,所以依然使用了变量的
表示方法。但其的值又 是不允许改变的,所以又符合常量的特征。这如同 C 语言里的 const 限定符,即这些常变量
通常是编译器限定不允许修改的,如 $EXEPATH 、 $EXEFILE 都属于常变量。实际上,通过插件仍可以修改这些所谓
的常量。这就是为什么帮助文档中说:从技术上来说你可以更改这个变量,但这并不是一个好主意。在 .onInit 函
数中该变量值为 0 ,因为此时窗口尚未创建,从 .onGUIInit 开始才有效。 在 .onGUIInit 函数中,我们可以通过
GetDlgItem 来获取主窗口上的按钮句柄。比如,上一步、下一步、取消等按钮 :

GetDlgItem $R0 $HWNDPARENT 1
 EnableWindow $R0 0

以便控制它们。如果要控制当前页面 (子窗口) 上的控件,我们要先 查找当前页面对话框的窗口句柄, 其 NSIS 脚
本 语法 为:

FindWindow $R0 "#32770" "" $HWNDPARENT

而如果在插件中,我们查找子窗口句柄,可以使用下面的 C/C++ 代码:

HWND hwndDialog = FindWindowEx(hwndParent, NULL, WC_DIALOG, NULL);

其中 WC_DIALOG 亦可使用 TEXT(“#32770”) 代替。至于这里为何是 32770 而不是其他数值,这个是微软规定的,
没有什么原因。 得到子窗口句柄之后,就 可以通过 GetDlgItem 来获取子窗口上的控件句柄,来控制当前页面的某
些控件,方法和获得父窗口上的控件句柄一致。

 第二个参数 string_size 代表 NSIS 的变量长度。这个概念可能有些人不懂了,变量还有长度?实际上, NSIS
脚本中, 变量 是没有 数据 类型的,他们都是统一长度的字符串类型, 并且所有的 变量都是等长的, 变量的地址 也 是
连续的 。 至于各个变量是如何存储的,将在下一个参数说明中介 绍 。 官方标准版本中变量的长度预定 为 1024
容纳 1023 个英文字符或 511 个中文字符。这个中文字符长度是针对 ANSI 版, Unicode 版则可以容纳 1023 个中
英 文字符。官方也 提供 8192 字节的版本 ,可根据需要选择。 你也可以自行编译 NSIS 来修改这个长度为其他数值,
最好是 4 的整倍数 。在 NSIS 源码中,它是通过宏 NSIS_MAX_STRLEN 来定义的。而在脚本中,它被 编译器预定义
为个译期常 ${NSIS_MAX_STRLEN} 。 虽是量但其用定常的别 该量值法
过 !undef 和 !define 进行改变。

 第三个参数 variables 代表 NSIS 中内部变量的首地址。 上面提到, NSIS 中所有的变量都是等长的,且在内

永恒心锁,版权所有丨如未注明,均为转载丨本网站采用BY-NC-SA协议进行授权

转载请注明:永恒心锁-分享互联网 » NSIS 插件开发 规范

您必须 登录 才能发表评论!