NSIS 中调用内核函数的基本理解
Basic understanding of calling kernel functions in NSIS
在 NSIS 中,我经历了一些 API,它调用了 Windows 的一些函数。
例如:
Kernel32::SetEnvironmentVariable(t, t)i ("VAR1", "$R0").r0
Kernel32::GetLocaleInfo(i,i,t,i)i(2048,0x2,.r0,${NSIS_MAX_STRLEN})i
由于我是新手,谁能解释一下这里发生了什么?什么是 t
、 i
、 .ro
等等?
我知道kernel32
是一个DLL,SetEnvironmentVariable
& GetLocaleInfo
是这个DLL中定义的函数。
The documentation 会告诉你 t
和 i
是什么。
System::Call 的基本语法是 module::function(parameters)return
。参数和 return 是可选的,它们都遵循相同的基本格式:类型输入输出。如果您需要输入 and/or 输出,则类型不是可选的。
参数和 return 可以重复多次,这仅在函数原型作为定义存在时才有用,但有时您也会在 NSIS Wiki 上看到这种语法。 Kernel32::SetEnvironmentVariable(t, t)i ("VAR1", "$R0").r0
与 Kernel32::SetEnvironmentVariable(t "VAR1", t "$R0")i.r0
完全相同。使用定义时,它看起来像这样:
!define SetEnvironmentVariable "Kernel32::SetEnvironmentVariable(t, t)i"
System::Call '${SetEnvironmentVariable}("VAR1", "$R0").r0'
如果您了解 C/C++ 或 Delphi 等语言,在使用系统插件时会很有帮助,因为您需要了解基本的 Windows 类型及其功能通常使用。
例如,如果您想调用 GetWindowsDirectory 函数,您首先要 look at the function on MSDN:
UINT WINAPI GetWindowsDirectory(_Out_ LPTSTR lpBuffer, _In_ UINT uSize);
将其转换为 NSIS 可为您提供 Kernel32::GetWindowsDirectory(t, i)i
的初始框架(WINAPI 是默认调用约定)。 t
映射到 Windows TCHAR*
类型, i
是一个 32 位整数,与 ULONG
, LONG
, [=25] 相同=]、INT
、UINT
、INT32
和 UINT32
在 Windows SDK 中。
唯一缺少的部分是输入和输出。 MSDN 声明用 SAL 注释修饰,因此很容易看出哪些参数是输入的,哪些是输出的。
一个工作示例可能如下所示:
System::Call 'Kernel32::GetWindowsDirectory(t .r1, i ${NSIS_MAX_STRLEN})i .r0'
DetailPrint "Return=[=12=] Output1="
.
可以在没有输入的时候作为"nothing"的占位符。在这种情况下,我们使用它两次。使用 System::Call 时 return 值永远不会有输入,我们还有一个仅输出参数。
r1
和 r0
是 </code> 和 <code>[=34=]
NSIS 寄存器的别名,当您需要输出某些内容时必须使用这些别名。普通的 NSIS 寄存器可以用作输入,但变量扩展发生在 NSIS 内部而不是插件中,这可能会导致字符串中的引号出现问题,如果字符串可能包含引号或合法的系统插件,则不推荐使用句法。因此,我建议将您的第一个示例重写为 Kernel32::SetEnvironmentVariable(t "VAR1", t R0)i.r0
.
在 C 中你的第二个例子看起来像
char mybuf[1024];
GetLocaleInfo(MAKELCID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT), LOCALE_SLANGUAGE, mybuf, sizeof(mybuf));
在 NSIS 中,我经历了一些 API,它调用了 Windows 的一些函数。
例如:
Kernel32::SetEnvironmentVariable(t, t)i ("VAR1", "$R0").r0
Kernel32::GetLocaleInfo(i,i,t,i)i(2048,0x2,.r0,${NSIS_MAX_STRLEN})i
由于我是新手,谁能解释一下这里发生了什么?什么是 t
、 i
、 .ro
等等?
我知道kernel32
是一个DLL,SetEnvironmentVariable
& GetLocaleInfo
是这个DLL中定义的函数。
The documentation 会告诉你 t
和 i
是什么。
System::Call 的基本语法是 module::function(parameters)return
。参数和 return 是可选的,它们都遵循相同的基本格式:类型输入输出。如果您需要输入 and/or 输出,则类型不是可选的。
参数和 return 可以重复多次,这仅在函数原型作为定义存在时才有用,但有时您也会在 NSIS Wiki 上看到这种语法。 Kernel32::SetEnvironmentVariable(t, t)i ("VAR1", "$R0").r0
与 Kernel32::SetEnvironmentVariable(t "VAR1", t "$R0")i.r0
完全相同。使用定义时,它看起来像这样:
!define SetEnvironmentVariable "Kernel32::SetEnvironmentVariable(t, t)i"
System::Call '${SetEnvironmentVariable}("VAR1", "$R0").r0'
如果您了解 C/C++ 或 Delphi 等语言,在使用系统插件时会很有帮助,因为您需要了解基本的 Windows 类型及其功能通常使用。
例如,如果您想调用 GetWindowsDirectory 函数,您首先要 look at the function on MSDN:
UINT WINAPI GetWindowsDirectory(_Out_ LPTSTR lpBuffer, _In_ UINT uSize);
将其转换为 NSIS 可为您提供 Kernel32::GetWindowsDirectory(t, i)i
的初始框架(WINAPI 是默认调用约定)。 t
映射到 Windows TCHAR*
类型, i
是一个 32 位整数,与 ULONG
, LONG
, [=25] 相同=]、INT
、UINT
、INT32
和 UINT32
在 Windows SDK 中。
唯一缺少的部分是输入和输出。 MSDN 声明用 SAL 注释修饰,因此很容易看出哪些参数是输入的,哪些是输出的。
一个工作示例可能如下所示:
System::Call 'Kernel32::GetWindowsDirectory(t .r1, i ${NSIS_MAX_STRLEN})i .r0'
DetailPrint "Return=[=12=] Output1="
.
可以在没有输入的时候作为"nothing"的占位符。在这种情况下,我们使用它两次。使用 System::Call 时 return 值永远不会有输入,我们还有一个仅输出参数。
r1
和 r0
是 </code> 和 <code>[=34=]
NSIS 寄存器的别名,当您需要输出某些内容时必须使用这些别名。普通的 NSIS 寄存器可以用作输入,但变量扩展发生在 NSIS 内部而不是插件中,这可能会导致字符串中的引号出现问题,如果字符串可能包含引号或合法的系统插件,则不推荐使用句法。因此,我建议将您的第一个示例重写为 Kernel32::SetEnvironmentVariable(t "VAR1", t R0)i.r0
.
在 C 中你的第二个例子看起来像
char mybuf[1024];
GetLocaleInfo(MAKELCID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT), LOCALE_SLANGUAGE, mybuf, sizeof(mybuf));