Archive: Require Windows XP Service Pack 2 (or later)


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}


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}


@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.)

@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

@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


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

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