PDA

View Full Version : Require Windows XP Service Pack 2 (or later)


drjasonharrison
23rd December 2009, 00:45
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_QueryAssemblyInfo_to_check_if_assembly_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, 03:47
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, 11:20
@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, 16:16
@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, 16:18
@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, 16:52
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, 17:00
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