nsis - NSIS 获取产品版本解决方案失败
问题描述
我一直在尝试使用系统调用 GetFileVersionInfo 和 VerQueryValue 来获取 exe 的产品版本。我使用的是旧版 NSIS v2.0b3(很多脚本已经在使用,只是想做一点点改动)。
在搜索了一段时间后,我 从一个 exe 中看到了这个解决方案产品版本字符串 - nssis ...但是在让它正常工作时遇到问题。
主要电话似乎工作......即
System::Call 'VERSION::GetFileVersionInfo(tr3,i,ir4,ir5)i.r0'
MessageBox MB_OK "GetFileVersionInfo returned dwLen=[$4] and lpData=[$5] for the block of Version Info"
...以 5 美元显示一个合理的 ptr。下一个电话是事情出错的地方......
System::Call 'VERSION::VerQueryValue(ir5,t"\",*i.r6,*i.r7)i.r0'
StrCmp $0 0 fail
MessageBox MB_OK "VS_FIXEDFILEINFO returned as lplpBuffer=[$6] and PUINT=[$7]"
此调用为 6 美元和 7 美元返回 0,0。然后当然解析失败......
;;---Parse buffer at $6 (lplp)
System::Call '*$6(i,i,i,i,i.r2,i.r1)'
MessageBox MB_OK "Read data from struct @$6: skip 4 ints then ints are dwProductVersionMS:[$2] dwProductVersionLS:[$1]"
...返回 0,0。
我认为问题是这里的 $6 中的间接指针。也就是说,$6 是类型 LPVOID *lplpBuffer ....所以我认为设置 $6 值的调用的语法可能需要不同。
欢迎任何帮助......我尝试了一些变化但没有成功。
===发布以下请求,这是我尝试过的许多变体中的最新版本......希望这将有助于澄清我在做什么===
Function GetDllProductVersion
; https://stackoverflow.com/questions/34616470/nsis-get-product-version?rq=1
; https://stackoverflow.com/questions/38707235/product-version-string-from-an-exe-nsis slightly different System::Call's, but also later nsis not compatible
;;System::Store S ;;;removed this and the matching Store L, as that crashes
Pop $3
;; System::Call 'VERSION::GetFileVersionInfoSize(tr3,*i)i.r4'
;; MessageBox MB_OK "GetFileVersionInfoSize gets size [$4]" ; cannot get a sensible answer, returns "error" in $4
;;---allocate block, address into $5
StrCpy $4 0
IntOp $4 $4 + 10000 ; set $4 to 10000
System::Call '*(&i$4,t""r1,t""r2)i.r5' ; Set $1 and $2 to "" so they are empty if we fail
MessageBox MB_OK "System::Call allocs [$4] bytes at addr [$5], next call GetFileVersionInfo"
StrCmp $4 0 fail
StrCmp $5 0 fail
;;---GetFileVersionInfo now-----
System::Call 'VERSION::GetFileVersionInfo(tr3,i,ir4,ir5)i.r0' ;; ir5 not isr5 ?? diff between solutions
StrCmp $0 0 fail
MessageBox MB_OK "GetFileVersionInfo returned dwLen=[$4] and lpData=[$5] for the block of Version Info"
;;---Now we get the VS_FIXEDFILEINFO structure using $5.... $6 will be lplpBuffer for it and $7 will be PUINT ptr to size of data in lplpBuffer
System::Call 'VERSION::VerQueryValue(ir5,t"\",*i.r6,*i.r7)i.r0' ;; using &i.r6 etc, not *i.r6 gives 0,0 no good, go back to *
StrCmp $0 0 fail
MessageBox MB_OK "VS_FIXEDFILEINFO returned as lplpBuffer=[$6] and PUINT=[$7]"
;;---Parse buffer at $6 (lplp)
System::Call '**$6(i,i,i,i,i.r2,i.r1)'
MessageBox MB_OK "Read data from struct @$6: skip 4 ints then ints are dwProductVersionMS:[$2] dwProductVersionLS:[$1]"
;;;or?????
System::Call '**$6(i,i,i,i,&i.r2,&i.r1)'
MessageBox MB_OK "Read data using & from struct @$6: skip 4 ints then ints are dwProductVersionMS:[$2] dwProductVersionLS:[$1]"
fail:
System::Free $5
MessageBox MB_OK "After System::Free [$5]"
Push $1
Push $2
;;System::Store L ;;;this crashes!!! so push and pop indiv registers used
FunctionEnd
解决方案
我无法解释为什么会System::Store
崩溃,即使在 v2.0b3 中它也可以正常工作。再说一次,您使用的是 15 年前的测试版软件,所以您不能指望一切都能正常工作。可能与在 v2.23(11 年前)中修复的错误 #1620178 有关。
您的主要问题是 v2.0b3 不自动支持带后缀的函数名称A
(大多数函数采用/返回字符串)。似乎在 v2.0b4 中添加了对此的支持。
您可以通过硬编码后缀来修改您发现兼容的代码:
Function GetDllProductVersion
Exch $3
Push $1
Push $2
Exch 2
Push $4
Push $5
Push $6
Push $7
Push $0
System::Call 'VERSION::GetFileVersionInfoSizeA(tr3,*i)i.r4'
System::Call '*(&i$4,t""r1,t""r2)i.r5' ; Set $1 and $2 to "" so they are empty if we fail
StrCmp $4 0 fail
StrCmp $5 0 fail
System::Call 'VERSION::GetFileVersionInfoA(tr3,i,ir4,ir5)i.r0'
StrCmp $0 0 fail
System::Call 'VERSION::VerQueryValueA(ir5,t"\",*i.r6,*i.r7)i.r0'
StrCmp $0 0 fail
System::Call '*$6(i,i,i,i,i.r2,i.r1)'
fail:
System::Free $5
Pop $0
Pop $7
Pop $6
Pop $5
Pop $4
Pop $3
Exch $1
Exch
Exch $2
FunctionEnd
Section
!define DllName "c:\windows\system32\ComCtl32.dll"
Push "${DllName}"
Call GetDllProductVersion
Pop $R0
Pop $R1
IntOp $R2 $R0 / 0x00010000
IntOp $R3 $R0 & 0x0000FFFF
IntOp $R4 $R1 / 0x00010000
IntOp $R5 $R1 & 0x0000FFFF
DetailPrint 'ProdVer: $R2.$R3.$R4.$R5'
SectionEnd
但我强烈建议您升级到更新的版本。至少 v2.51 以获取所有安全修复程序。
推荐阅读
- python - 遍历 dict 或其键并更改值是不好的做法吗?
- javascript - 量角器茉莉花测试中的异步代码执行
- jinja2 - json文件中循环识别错误的jinja2模板
- jquery - jquery show() 在 setTimeout() 方法后不起作用
- ajax - jsp-如何将值发送到数据库表进行处理?
- google-cloud-platform - 关于谷歌云平台报错:请求的54.0 CPUs超过了允许的最大值20.0
- python - 将 dicttoxml json 转储合并到一个 xml 文件
- php - 如何在laravel中使用mpdf为每个页面添加水印
- android - Android 不均匀设计
- arrays - 将从外部 Url 返回的 JSON 反序列化为 Object