Archive: My NSIS check for JRE is broken


My NSIS check for JRE is broken
  It is probably my code that is broken, but why does this code try to install the jre? I verified that C:\Windows\System32\java.exe does in fact exist, but this code doesn't see it. The method is lifted from http://forums.winamp.com/showthread.php?postid=1955725.

${If} ${FileExists} `$SYSDIR\java.exe`
; Skip JRE install
${Else}
${If} ${RunningX64}
ExecWait '"jre-6u22-windows-x64.exe"'
${Else}
ExecWait '"jre-6u22-windows-i586-s.exe"'
${EndIf}
${EndIf}

Are you running the installer on 64-bit Windows? If so $SYSDIR would actually be C:\Windows\SysWOW64, and maybe the 32-bit Java isn't installed but the 64-bit one is in C:\Windows\System32.


and as you're using the RunningX64 LogicLib extension you probably included x64.nsh which allows you to turn off the redirection that happens when a 32bit app accesses $SYSDIR.

Note that if you're targeting only Vista+, you can alternatively access $WINDIR\SysNative\ (not available on XP unless the user installed an optional (not distributed through Windows Updates) hotfix).


This script is targeting XP, Vista, 32 bit, and 64 bit. It does include x64.nsh and is modified based on clues from redxii and Animaether to work for all cases, but it still misbehaves. Is the logic bogus? Is the use of `C:\Windows\System32\java.exe` improper?

; Check for Java Runtime Environment (JRE)
${If} ${FileExists} `$SYSDIR\java.exe`
; Skip JRE install
${ElseIf} ${FileExists} `C:\Windows\System32\java.exe`
; Skip JRE install
${ElseIf} ${RunningX64}
ExecWait '"jre-6u22-windows-x64.exe"'
${Else}
ExecWait '"jre-6u22-windows-i586-s.exe"'
${EndIf}

I'm not sure that logic is entirely correct... (I'm not sure detecting java being installed by checking for java.exe is correct either, but let's run with that...)

${Unless} ${FileExists} "$SYSDIR\java.exe"

/* perform 32bit install */
>${EndIf}
${If} ${RunningX64}
${DisableX64FSRedirection}
${Unless} ${FileExists} "$SYSDIR\java.exe"
/* perform 64bit install */
${EndIf}
${EnableX64FSRedirection}
${EndIf}
or (Only if you target Vista+, not XP)
${Unless} ${FileExists} "$SYSDIR\java.exe"

/* perform 32bit install */
>${EndIf}
${If} ${RunningX64}
${Unless} ${FileExists} "$WINDIR\SysNative\java.exe"
/* perform 64bit install */
${EndIf}
${EndIf}

Originally posted by Animaether
... (I'm not sure detecting java being installed by checking for java.exe is correct ...)
On my system (Win 7 Ultimate 32Bit) the detection will succeed (${ElseIf} ${FileExists} `C:\Windows\System32\java.exe`).

Maybe some other/ additional options for detection:
- Regkey (HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft), I don't know where it would be on x64 systems
- "Normally" if JRE is installed it is also added to the path variable

Gunther

Oh I'm sure it works... I'm just saying that I'm not sure it's "correct"... let me choose another word there: "appropriate" :)


Originally posted by Animaether
Oh I'm sure it works... I'm just saying that I'm not sure it's "correct"... let me choose another word there: "appropriate" :)
What is the "appropriate" method?

On Windows, the ARP registry tends to be the most suitable in cases where the vendor doesn't offer any guidelines (and it doesn't look like Oracle/Sun do, except for end-users... click this, open that, look here, click there.. yikes.).

This...
http://wpkg.org/Java#Java_Runtime_En...29_6_Update_10
...might be a good place to start peeking.

Mind you - I'm not saying that checking for java.exe is wrong.. it's probably perfectly fine and if you don't notice any negative effects, it's a lot simpler than going through the above.


What is incorrect with my logic? Also: it looks like what you suggest below (in the first if block) will want to reinstall the jre if java.exe is in Windows\System32 on a 64 bit machine.

Originally posted by Animaether
I'm not sure that logic is entirely correct... (I'm not sure detecting java being installed by checking for java.exe is correct either, but let's run with that...)

${Unless} ${FileExists} "$SYSDIR\java.exe"

/* perform 32bit install */
>${EndIf}
${If} ${RunningX64}
${DisableX64FSRedirection}
${Unless} ${FileExists} "$SYSDIR\java.exe"
/* perform 64bit install */
${EndIf}
${EnableX64FSRedirection}
${EndIf}
or (Only if you target Vista+, not XP)
${Unless} ${FileExists} "$SYSDIR\java.exe"

/* perform 32bit install */
>${EndIf}
${If} ${RunningX64}
${Unless} ${FileExists} "$WINDIR\SysNative\java.exe"
/* perform 64bit install */
${EndIf}
${EndIf}

Originally posted by JackN
Also: it looks like what you suggest below (in the first if block) will want to reinstall the jre if java.exe is in Windows\System32 on a 64 bit machine.
Nope.. note that I use ${Unless}, not ${If}. Although I messed up and used closing ${EndIf} statements when they should be ${EndUnless}. Can't edit post anymore.. bugger :)

So basically it says this: -Unless- $SYSDIR\java.exe exists, install JAVA.

Originally posted by JackN
What is incorrect with my logic?
The logic in your post says this in a 64bit environment...
If $SYSDIR\java.exe, which is redirected to $WINDIR\SysWoW64\java.exe, exists -> Skip the install.
Otherwise if C:\Windows\System32\java.exe, which is also redirected.. to C:\Windows\SysWoW64\java.exe, exists -> skip the install

So basically, the filesystem redirection is what was mucking up the logic in your post.

This is what actually worked on a Vista-64 with javaw.exe in C:\Windows\System32\

${If} ${RunningX64} 

${DisableX64FSRedirection}
${Unless} ${FileExists} "$SYSDIR\javaw.exe"
ExecWait '"jre-6u22-windows-x64.exe"'
${EndUnless}
${EnableX64FSRedirection}
${Else}
${Unless} ${FileExists} "$SYSDIR\javaw.exe"
ExecWait '"jre-6u22-windows-i586-s.exe"'
${EndUnless}
${EndIf}
The original suggestion without the RunningX64/Else tried to install the 32 bit jre.
I suppose I'll find some combinations that break this logic but should be able to figure those out.
Thanks a million.

Sounds easier to just use an exe wrapper for your program that will automatically redirect the user to DL Java if they haven't already installed it; like Launch4J.

I'm not really sure since I haven't voluntarily used or installed Java for quite a while but it shouldn't matter what bit of Java launches the program standing alone. It's just that in a 32-bit browser/application you can only load the 32-bit version of Java and with a 64-bit browser/application you can only load the 64-bit version of Java. The 64-bit version of Java doesn't include 32-bit support.