NSIS Get Product Version 解决方案失败
NSIS Get Product Version solution failing
我一直在尝试使用系统调用 GetFileVersionInfo 和 VerQueryValue 来获取 exe 的产品版本。我使用的是旧版 NSIS v2.0b3(许多脚本已经在使用,只是想做一点改动)。
找了一段时间后看到了这个解决方案
...但在让它正常工作时遇到问题。
主调用似乎有效...即
System::Call 'VERSION::GetFileVersionInfo(tr3,i,ir4,ir5)i.r0'
MessageBox MB_OK "GetFileVersionInfo returned dwLen=[] and lpData=[] for the block of Version Info"
...显示 $5 的合理 ptr。
下一个电话是出了问题的地方...
System::Call 'VERSION::VerQueryValue(ir5,t"\",*i.r6,*i.r7)i.r0'
StrCmp [=11=] 0 fail
MessageBox MB_OK "VS_FIXEDFILEINFO returned as lplpBuffer=[] and PUINT=[]"
此呼叫 returns 0,0 为 6 美元和 7 美元。然后当然解析失败...
;;---Parse buffer at (lplp)
System::Call '*(i,i,i,i,i.r2,i.r1)'
MessageBox MB_OK "Read data from struct @: skip 4 ints then ints are dwProductVersionMS:[] dwProductVersionLS:[]"
...returns 0,0.
我认为问题出在此处 $6 中的间接指针。
也就是说,$6 是类型
LPVOID *lplpBuffer
....所以我认为设置 $6 值的调用语法可能需要不同。
欢迎任何帮助...我尝试了一些变化但没有成功。
===根据发布的请求,这是我尝试过的许多变化中的最新变化...希望这将有助于阐明我在做什么===
Function GetDllProductVersion
;
; 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
;; System::Call 'VERSION::GetFileVersionInfoSize(tr3,*i)i.r4'
;; MessageBox MB_OK "GetFileVersionInfoSize gets size []" ; cannot get a sensible answer, returns "error" in
;;---allocate block, address into
StrCpy 0
IntOp + 10000 ; set to 10000
System::Call '*(&i,t""r1,t""r2)i.r5' ; Set and to "" so they are empty if we fail
MessageBox MB_OK "System::Call allocs [] bytes at addr [], next call GetFileVersionInfo"
StrCmp 0 fail
StrCmp 0 fail
;;---GetFileVersionInfo now-----
System::Call 'VERSION::GetFileVersionInfo(tr3,i,ir4,ir5)i.r0' ;; ir5 not isr5 ?? diff between solutions
StrCmp [=13=] 0 fail
MessageBox MB_OK "GetFileVersionInfo returned dwLen=[] and lpData=[] for the block of Version Info"
;;---Now we get the VS_FIXEDFILEINFO structure using .... will be lplpBuffer for it and 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 [=13=] 0 fail
MessageBox MB_OK "VS_FIXEDFILEINFO returned as lplpBuffer=[] and PUINT=[]"
;;---Parse buffer at (lplp)
System::Call '**(i,i,i,i,i.r2,i.r1)'
MessageBox MB_OK "Read data from struct @: skip 4 ints then ints are dwProductVersionMS:[] dwProductVersionLS:[]"
;;;or?????
System::Call '**(i,i,i,i,&i.r2,&i.r1)'
MessageBox MB_OK "Read data using & from struct @: skip 4 ints then ints are dwProductVersionMS:[] dwProductVersionLS:[]"
fail:
System::Free
MessageBox MB_OK "After System::Free []"
Push
Push
;;System::Store L ;;;this crashes!!! so push and pop indiv registers used
FunctionEnd
我无法解释为什么 System::Store
会崩溃,据记载即使在 v2.0b3 中也能正常工作。再者,您使用的是 15 年前的 beta 软件,因此您不能指望一切正常。可能与在 v2.23(11 年前)中修复的错误 #1620178 有关。
您的主要问题是 v2.0b3 不自动支持以 A
为后缀的函数名称(大多数 take/return 字符串的函数)。似乎在 v2.0b4 中添加了对此的支持。
您可以通过硬编码后缀来修改您发现兼容的代码:
Function GetDllProductVersion
Exch
Push
Push
Exch 2
Push
Push
Push
Push
Push [=10=]
System::Call 'VERSION::GetFileVersionInfoSizeA(tr3,*i)i.r4'
System::Call '*(&i,t""r1,t""r2)i.r5' ; Set and to "" so they are empty if we fail
StrCmp 0 fail
StrCmp 0 fail
System::Call 'VERSION::GetFileVersionInfoA(tr3,i,ir4,ir5)i.r0'
StrCmp [=10=] 0 fail
System::Call 'VERSION::VerQueryValueA(ir5,t"\",*i.r6,*i.r7)i.r0'
StrCmp [=10=] 0 fail
System::Call '*(i,i,i,i,i.r2,i.r1)'
fail:
System::Free
Pop [=10=]
Pop
Pop
Pop
Pop
Pop
Exch
Exch
Exch
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 作为获得所有安全修复的最低要求。
我一直在尝试使用系统调用 GetFileVersionInfo 和 VerQueryValue 来获取 exe 的产品版本。我使用的是旧版 NSIS v2.0b3(许多脚本已经在使用,只是想做一点改动)。
找了一段时间后看到了这个解决方案
主调用似乎有效...即
System::Call 'VERSION::GetFileVersionInfo(tr3,i,ir4,ir5)i.r0'
MessageBox MB_OK "GetFileVersionInfo returned dwLen=[] and lpData=[] for the block of Version Info"
...显示 $5 的合理 ptr。 下一个电话是出了问题的地方...
System::Call 'VERSION::VerQueryValue(ir5,t"\",*i.r6,*i.r7)i.r0'
StrCmp [=11=] 0 fail
MessageBox MB_OK "VS_FIXEDFILEINFO returned as lplpBuffer=[] and PUINT=[]"
此呼叫 returns 0,0 为 6 美元和 7 美元。然后当然解析失败...
;;---Parse buffer at (lplp)
System::Call '*(i,i,i,i,i.r2,i.r1)'
MessageBox MB_OK "Read data from struct @: skip 4 ints then ints are dwProductVersionMS:[] dwProductVersionLS:[]"
...returns 0,0.
我认为问题出在此处 $6 中的间接指针。 也就是说,$6 是类型 LPVOID *lplpBuffer ....所以我认为设置 $6 值的调用语法可能需要不同。
欢迎任何帮助...我尝试了一些变化但没有成功。
===根据发布的请求,这是我尝试过的许多变化中的最新变化...希望这将有助于阐明我在做什么===
Function GetDllProductVersion
;
; 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
;; System::Call 'VERSION::GetFileVersionInfoSize(tr3,*i)i.r4'
;; MessageBox MB_OK "GetFileVersionInfoSize gets size []" ; cannot get a sensible answer, returns "error" in
;;---allocate block, address into
StrCpy 0
IntOp + 10000 ; set to 10000
System::Call '*(&i,t""r1,t""r2)i.r5' ; Set and to "" so they are empty if we fail
MessageBox MB_OK "System::Call allocs [] bytes at addr [], next call GetFileVersionInfo"
StrCmp 0 fail
StrCmp 0 fail
;;---GetFileVersionInfo now-----
System::Call 'VERSION::GetFileVersionInfo(tr3,i,ir4,ir5)i.r0' ;; ir5 not isr5 ?? diff between solutions
StrCmp [=13=] 0 fail
MessageBox MB_OK "GetFileVersionInfo returned dwLen=[] and lpData=[] for the block of Version Info"
;;---Now we get the VS_FIXEDFILEINFO structure using .... will be lplpBuffer for it and 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 [=13=] 0 fail
MessageBox MB_OK "VS_FIXEDFILEINFO returned as lplpBuffer=[] and PUINT=[]"
;;---Parse buffer at (lplp)
System::Call '**(i,i,i,i,i.r2,i.r1)'
MessageBox MB_OK "Read data from struct @: skip 4 ints then ints are dwProductVersionMS:[] dwProductVersionLS:[]"
;;;or?????
System::Call '**(i,i,i,i,&i.r2,&i.r1)'
MessageBox MB_OK "Read data using & from struct @: skip 4 ints then ints are dwProductVersionMS:[] dwProductVersionLS:[]"
fail:
System::Free
MessageBox MB_OK "After System::Free []"
Push
Push
;;System::Store L ;;;this crashes!!! so push and pop indiv registers used
FunctionEnd
我无法解释为什么 System::Store
会崩溃,据记载即使在 v2.0b3 中也能正常工作。再者,您使用的是 15 年前的 beta 软件,因此您不能指望一切正常。可能与在 v2.23(11 年前)中修复的错误 #1620178 有关。
您的主要问题是 v2.0b3 不自动支持以 A
为后缀的函数名称(大多数 take/return 字符串的函数)。似乎在 v2.0b4 中添加了对此的支持。
您可以通过硬编码后缀来修改您发现兼容的代码:
Function GetDllProductVersion
Exch
Push
Push
Exch 2
Push
Push
Push
Push
Push [=10=]
System::Call 'VERSION::GetFileVersionInfoSizeA(tr3,*i)i.r4'
System::Call '*(&i,t""r1,t""r2)i.r5' ; Set and to "" so they are empty if we fail
StrCmp 0 fail
StrCmp 0 fail
System::Call 'VERSION::GetFileVersionInfoA(tr3,i,ir4,ir5)i.r0'
StrCmp [=10=] 0 fail
System::Call 'VERSION::VerQueryValueA(ir5,t"\",*i.r6,*i.r7)i.r0'
StrCmp [=10=] 0 fail
System::Call '*(i,i,i,i,i.r2,i.r1)'
fail:
System::Free
Pop [=10=]
Pop
Pop
Pop
Pop
Pop
Exch
Exch
Exch
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 作为获得所有安全修复的最低要求。