nsis - 如何从 NSIS 中的 RCData 资源中读取字符串
问题描述
我在 RCData 资源中有一个 ANSI 字符串,我想将该字符串存储在一个变量中。我已经到了可以获取资源指针和数据大小的地步:
; HMODULE GetModuleHandle(LPCSTR lpModuleName);
System::Call "kernel32::GetModuleHandle(i 0) i.r0"
; HRSRC FindResource(HMODULE hModule, LPCSTR lpName, LPCSTR lpType);
System::Call "kernel32::FindResource(i 0, t 'DATA', i 10) i.r1"
; HGLOBAL LoadResource(HMODULE hModule, HRSRC hResInfo);
System::Call "kernel32::LoadResource(i r0, p r1) i.r2"
; LPVOID LockResource(HGLOBAL hResData);
System::Call "kernel32::LockResource(i r2) p.r3"
; DWORD SizeofResource(HMODULE hModule, HRSRC hResInfo);
System::Call "kernel32::SizeofResource(i r0, i r1) i.r4"
现在我不太确定该怎么做。我对 NSIS 很陌生,我认为我的问题是我并不真正了解变量在 NSIS 中是如何工作的,以及当变量用作具有不同类型的系统调用的输出时会发生什么(它具有什么值)。我需要什么(我认为)是将$4
字节从存储在其中的地址复制$3
到新缓冲区并(可能?)以零终止它。我认为这样的事情可以工作:
System::Alloc ${NSIS_MAX_STRLEN}
Pop $5
System::Copy /$4 $5 $3
但事实并非如此。经过一些实验,我明白了它的工作原理:
System::Call "*$3(&m$4.r5)"
但我真的不知道为什么这是有效的,如果这是处理这项任务的正确方式,以及为什么上面的复制版本不起作用。
解决方案
在 System::Copy 代码中,$5 包含分配的缓冲区的内存地址(作为字符串,就像有人这样做一样sprintf(reg5, "%i", address)
)。如果你这样做MessageBox mb_ok $5
,你只会看到这个地址。但是,如果你这样做,System::Call user32::MessageBoxA(p0,pr5,p0,i0)
你应该看到你的字符串。
System::Call 代码使用您指定的类型转换源和/或目标。这是一种完全有效的方法,并且比复制代码工作量少。
如果我们有一些需要类型转换而不是在您的特定情况下基本上是字节副本的东西,这可能更容易可视化。
想象一下,如果在 C 中我们有
typedef struct { int foo, bar; } MyS;
MyS*ptr = allocandfill();
在 NSIS 中 $1 是 ptr 的值:
System::Call '*$1(i.r2,i1234)'
我们通常将此称为 System struct 语法,而 * 可以被认为是取消引用从 $1 开始的内存,并将内存解释为基于我们指定的类型的结构。
在我的具体示例中,我们说第一个成员是一个 int,我不想更改值/源(点),但我希望当前值作为存储在 r2($2)中的输出。这将基本上执行itoa
$2 是目的地的情况。第二个成员是另一个 int,我用数字 1234 覆盖它的当前值。在 C 中,这将执行ptr->bar = atoi("1234")
.
完成任务的第三种方法是调用 Windows 函数并让它完成工作:
System::Call `kernel32::lstrcpyA(m.r5,pr3)' ; or lstrcpynA if the string is not zero-terminated or you want to chop it to n characters
推荐阅读
- javascript - 将 .py -> .html 值发送到 .js(Django、Mapbox)
- javascript - 在 JavaScript 中查找字符串中模式的重叠出现次数
- java - 我需要得到猜测的总数以及为猜谜游戏玩的游戏总数
- angular - Firebase:用户只能看到他添加到 Firebase 的内容。其他人不应看到其他用户的数据。如何?
- html - 如何从 column3 设置水平滚动条的起始位置,因为前两列是固定的(粘性)
- visual-studio-code - VSCode 删除 Linux 上的白色文件菜单
- javascript - 在数组中搜索两个加起来为总和值的数字时,我的嵌套 for 循环超时
- c++ - 二项分布的正确实施?
- go - 使用绝对路径构建包路径
- python - 尝试在 YoutubeAnalytics Api 中使用 Pandas 解析 JSON 并将其转换为 CSV