drjasonharrison
23rd December 2009 01:45 UTC
Require Windows XP Service Pack 2 (or later)
Hi,
I've tried to use WinSxS_HasAssembly but I've found that it is to rigid in it's acceptance of the version of the MSCVR80.dll. See http://nsis.sourceforge.net/WinSxS_Q...y_is_installed
I have on one machine version 8.0.50727.42 and on another 8.0.50727.762. I need either of these to be acceptable.
Can someone please explain what is happening in this code that would reject based on the rebuild version of the dll and how to fix that?
-Jason
System::Call "sxs::CreateAssemblyCache(*i.R0,i0)i.r0"
${If} $0 == 0
System::Call '*(i 24,i0,l,i0,i0)i.R1' ;TODO,BUGBUG: check alloc success
System::Call `$R0->4(i 0,w '$8',i $R1)i.r0` ;IAssemblyCache::QueryAssemblyInfo
${If} $0 == 0
System::Call '*$R1(i,i.r0)'
IntOp $0 $0 & 1 ;ASSEMBLYINFO_FLAG_INSTALLED=1
${IfThen} $0 <> 0 ${|} StrCpy $9 1 ${|}
${EndIf}
System::Free $R1
System::Call $R0->2() ;IAssemblyCache::Release
${EndIf}
msroboto
23rd December 2009 04:47 UTC
Why don't you use Winver.nsh?
Look it up in the wiki if my link doesn't work.
http://nsis.sourceforge.net/Include/WinVer.nsh
${If} ${IsWinXP}
${AndIf} ${AtLeastServicePack} 2
DetailPrint "Running WinXP SP2 or above"
${EndIf}
Anders
23rd December 2009 12:20 UTC
@drjasonharrison: That code itself does not really care about the specific version, it just asks windows. The only thing I could think of is to not check for the ASSEMBLYINFO_FLAG_INSTALLED flag, but just check if the call to IAssemblyCache::QueryAssemblyInfo succeeded or not.
The code would then simply be:
System::Call "sxs::CreateAssemblyCache(*i.R0,i0)i.r0"
${If} $0 == 0
System::Call '*(i 24,i0,l,i0,i0)i.R1' ;TODO,BUGBUG: check alloc success
System::Call `$R0->4(i 0,w '$8',i $R1)i.r0` ;IAssemblyCache::QueryAssemblyInfo
${If} $0 == 0
StrCpy $9 1
${EndIf}
System::Free $R1
System::Call $R0->2() ;IAssemblyCache::Release
${EndIf}
(NOTE: I don't know anything or care about SxS (And the MS documentation about it sucks), just checking the return might give false positives (or not work at all) etc.)
drjasonharrison
23rd December 2009 17:16 UTC
@Anders
Well, the code changes it's behaviour -- if the rebuild version does not match exactly then it fails. However as you point out perhaps the issue is the system call care more.
I believe the check against the version number occurs here:
System::Call '*$R1(i,i.r0)'
IntOp $0 $0 & 1 ;ASSEMBLYINFO_FLAG_INSTALLED=1
${IfThen} $0 <> 0 ${|} StrCpy $9 1 ${|}
However I don't understand what the ${|} operator is doing. Is this documented somewhere? It's rather hard to google or search the NSIS windows help for ${|}.
-Jason
drjasonharrison
23rd December 2009 17:18 UTC
@msroboto
Thank you for recommending WinVer, I will try it. Unfortunately my search on the NSIS website for "service pack" and other keywords brought me to the other solution.
-Jason
drjasonharrison
23rd December 2009 17:52 UTC
I'm trying this:
var /GLOBAL osVersion
${If} ${IsWinXP}
${AndIf} ${AtLeastServicePack} 2
StrCpy $osVersion 'WinXP SP2'
${Else}
MessageBox MB_OK|MB_ICONEXCLAMATION "Product requires Windows XP Service Pack 2 or later." Abort
${EndIf}
${If} ${IsAtLeastVista}
StrCpy $osVersion 'VistaOrLater'
${EndIf}
But the NSIS compiler is complaining about the ${If} ${IsAtLeastVista} line:
Var: "osVersion"
!insertmacro: _If
!insertmacro: end of _If
!insertmacro: _And
!insertmacro: end of _And
StrCpy $osVersion "WinXP SP2" () ()
!insertmacro: _Else
!insertmacro: end of _Else
MessageBox: 48: "Product requires Windows XP Service Pack 2 or later."
Abort: ""
!insertmacro: _EndIf
!insertmacro: end of _EndIf
!insertmacro: _If
!insertmacro: macro "_If" requires 4 parameter(s), passed 2!
Suggestions?
-Jason
drjasonharrison
23rd December 2009 18:00 UTC
Okay, found it. I should have used ${AtLeastWinVista}.
My trick was to put the ${IsAtLeastVista} on it's own line and then the compiler told me that it couldn't recognize that variable/macro. Which led me to reading the WinVer.nsh documentation a bit closer.
-Jason