To get only 64 bit JRE value from Windows Registry - java

As i am from testing background and have a very limited knowledge on Java kindly excuse me if the question i have asked is not good or repetitive.
I am trying to build an application using Java Swing. As per the requirement I have to display 32 bit Jre or 64 bit Jre installed on laptop based on the selection made. Frame which i developed for this
Unfortunately when I tested by installing a 32 bit JRE on Windows 64 bit machine and tried to run my application, when I choose the radio button "64 bit JRE" , in the drop down list its displaying me the 32 bit JRE which is installed on my system. (Kindly note i do not have any 64 bit JRE installed on my system). Ideally it should not display anything but the default value set in the JComboBox. :(
I understood the JRE was picked due to the Windows property. I tried with the API Advapi32.INSTANCE using the method RegGetValue but i am unable to get the value from Windows Registry.
32 bit JRE are under the path : HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node \JavaSoft\Java Runtime Environment
and 64 bit JRE are under the path : HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment
Please find the below code which i tried to retrieve 64 bit JRE :
String[] val64 = RegistryCheck.getRegistryDataForJRE(HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Runtime Environment");
public static String[] getRegistryDataForJRE(WinReg.HKEY root, String key) {
if (Advapi32Util.registryKeyExists(root, key)) {
return Advapi32Util.registryGetKeys(root, key);
} else {
return null;
}
}
Also below is the code which i tried with Advapi32.INSTANCE (just ttried to do a sysout to know whether the value returned is 0 or not. as from the Microsoft pages i see if its a non zero value returned its an error
public static void main(String[] args) {
byte[] b = new byte[50];
IntByReference pcbData = new IntByReference(50);
System.out.println(Advapi32.INSTANCE.RegGetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Runtime Environment",
"" , 0x0200, pcbData, b, pcbData));
}
Also, I read the flag KEY_WOW64_32KEY is the responsible to pick up from the WOW6432Node , but i am not able to check the flag value or to set it to false in java.
Can anyone help me with this issue ?
I would be really grateful for the help.
Thank you in advance for the support.

try to use the method RegOpenKeyEx() of Advapi32 i.e. syntax
RegOpenKeyEx(WinReg.HKEY hKey,
String lpSubKey,
int ulOptions,
int samDesired,
WinReg.HKEYByReference phkResult)
refer to the link RegOpenKeyEx()
You can pass the parameters accordingly and then check if the return value is "0" then the path exists in 64 bit else it doesn't exists.
Note : when you pass "samDesired" into the RegOpenKeyEx() pass the combination of KEY_QUERY_VALUE and KEY_WOW64_64KEY
For example :
WinReg.HKEYByReference hKey = new HKEYByReference();
Advapi32.INSTANCE.RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Runtime Environment",0, 0x0001 | 0x0100, hKey);
Let me know if it worked for you

Related

Java 8 os.version does not contain entire Windows version

For Windows 10, Java 8 returns os.version=10.0 from System Properties, while the Windows 'ver' command returns 10.0.14393.
Is there any way to get the full windows version from java without running an external command?
Why is Java truncating the Windows version?
The answer is, as ever, in the code - it's not that it's truncating it; it just never populates the build number.
Looking at the jdk8 source, they only populated dwMajorVersion and dwMinorVersion:
sprintf(buf, "%d.%d", ver.dwMajorVersion, ver.dwMinorVersion);
sprops.os_version = _strdup(buf);
It's been this way since at least the jdk6.
Now, if you want to get a full windows version, including the build, then you can use JNA - the classes/interfaces you're looking for is com.sun.jna.platform.win32.WinNT, which contains the VERSIONINFOEX structure, and com.sun.jna.platform.win32.Kernel32 for the GetVersionEx function. I don't have a copy of windows to stub out the code for you; but it should be relatively easy to do (maybe something like this? I can't even try to test this out):
import com.sun.jna.platform.win32.*;
import java.text.MessageFormat;
public static void main(String args[]) {
Kernel32 kernel = Kernel32.INSTANCE;
WinNT.OSVERSIONINFOEX vex = new WinNT.OSVERSIONINFOEX();
if (kernel.GetVersionEx(vex)) {
System.out.println(MessageFormat.format("{0}.{1}.{2}",
vex.dwMajorVersion.toString(),
vex.dwMinorVersion.toString(),
vex.dwBuildNumber.toString()));
}
}
Asking for a rationale for this; it's pretty simple really - it never really mattered before windows 10 - you had strong delineations of behaviour based on the major and minor version of the OS; with the introduction of features by build for windows 10 it's complicated things.

how windows will do auto java update checks?

First of all sorry for my poor English.
I want to know how the windows will do auto java update check behind the User Interface ?
The UI will just react based on our input which is in the link , http://java.com/en/download/help/java_update.xml#howto .
But , how windows checks the updates programmatically.
I wrote a small program in java ,
public class JavaLatestVersion {
public static void main(String[] args){
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new URL(
"http://java.com/applet/JreCurrentVersion2.txt").openStream())) ;
String fullVersion = br.readLine();
System.out.println("fullVersion : "+fullVersion);
String version = fullVersion.split("_")[0];
String revision = fullVersion.split("_")[1];
System.out.println("Version " + version + " revision " + revision);
} catch (IOException e) {
e.printStackTrace();
}
}
}
My questions :
1. Is the above program is the reliable way to get the latest java version ? Or any other standard way to get the latest java version (Not in the computer) ?
2. Is windows use the same way to determine the latest java version ?
3. Is windows use this link for updates http://java.com/applet/JreCurrentVersion2.txt ?
Any one know the secret code behind how windows will check for latest java updates?
Thanks in advance.
Checking for Java updates is done by Java Auto Updater. It is ordinary application (which is ran when Windows starts up).
Yes, it is reliable way to get the latest version of Java (as updater can not only update Java, it can also update itself). But pay attention to firewall/group policy settings which can prohibit updater to access the Web.
Windows doesn't update Java.
Only debugging Java Auto Updater can help to determine what URL it uses.
Unfortunately, Java Auto Updater has only graphical interface and hides all work behind the scenes. So finding a "secret code" is not easy to do. All the more in many cases reverse-engineering non-open source software is illegal from a license point of view.
URL that you provided above doesn't works. Because it says 8.0_51. But latest version of Java on Downloads page is 8u65 / 8u66.
Seems that latest available version (as plain text) can be determined only by fetching http://www.oracle.com/technetwork/java/javase/downloads/index.html web page, then parsing it, handling cases when page is moved to another location, etc.

Java - get "program files" path

How can I get the current computer's "Program Files" path with Java?
Simply by calling System.getenv(...)
System.getenv("ProgramFiles");
Notice it will only work in Windows environments, of course :-)
System.getenv("%programfiles% (x86)");
for the 32-bit folder on 64-bit PC's.
Also, it works on any language in Windows Vista and newer. Calling either of the posted responses will work on any language installation, in fact.
For 32 bit use:
System.out.println(System.getenv("ProgramFiles(X86)"));
For 64 bit use:
System.out.println(System.getenv("ProgramFiles"));
Use the System.getenv() method:
public class EnvironmentVariableExample {
public static void main(String[] args) {
System.out.println(System.getenv("ProgramFiles"));
System.out.println(System.getenv("MadeUpEnvVar"));
}
}
If the variable doesn't exist, it will simply return null.

The method split(String) is undefined for the type String

I am using Pulse - the Plugin Manager for Eclipse and installed. I have the Eclipse 3.5 for mobile development(Pulsar) profile with a couple other profiles.
I realized that the split() method called on a string from code such as below:
String data = "one, two, three, four";
data.split(",");
generates the error: "The method split(String) is undefined for the type String". I am aware that the split() method did not exist before Java's JRE 1.4 and perhaps could be the cause of the problem.
The problem is I don't think I have jre/sdk versions installed. Perhaps there's one in-built with the Pulsar profile and needs editing - but I couldn't tell what settings (and where) needs tweaking. I have checked Windows>Preferences>Java>Installed JREs and it's set to >= jre1.4.
I note "Eclipse 3.5 for mobile development". Maybe this tool expects to run J2ME, which I believe is several issues behind J2SE.
This page gives links to the JavaDoc for the various APIs in JME. There are several versions, (follow the links under CLDC and CDC and look for java.lang.String) but as far as I can tell none of them define String.split().
String.split method is introduced from Java version 1.4 onward, if you have same job to be done you may give a try to this:
public String[] splitStr(String str, String delim) {
StringTokenizer stringTokenizer = new StringTokenizer( str, delim );
String[] strArr = new String[stringTokenizer.countTokens()];
int i = 0;
while( stringTokenizer.hasMoreTokens() ) {
strArr[i] = stringTokenizer.nextToken();
}
return strArr;
}
Last time I looked (in a Windows XP installation), I found the default installed JVM to be 1.3 .
You could pop open a "DOS shell" (err, command prompt) and type java -version to see the truth at least about whatever Java is on the PATH.
I would definitely recommend installing an up-to-date JDK. The JDK includes a compiler and other tools, that's more useful to a developer than just a JRE. You then need to go back into Eclipse's preferences and point its JDK/JRE settings at your newly installed JDK.
String data = "one, two, three, four";
data.split(",");
are you declaring
String[] variable
example
String[] variable = data.split(",");
for(String value: variable){
System.out.println(value);
}
I tried it its working on it
i got the same issue but its for replaceAll(arg1,arg2) method and resolved when i changed order of jre version . for eg i m using jre 8 then order should in java build path: rank fiest in " order and export". JRE library

Pinning a Java application to the Windows 7 taskbar

I use Launch4j as a wrapper for my Java application under Windows 7, which, to my understanding, in essence forks an instance of javaw.exe that in turn interprets the Java code. As a result, when attempting to pin my application to the task bar, Windows instead pins javaw.exe. Without the required command line, my application will then not run.
As you can see, Windows also does not realize that Java is the host application: the application itself is described as "Java(TM) Platform SE binary".
I have tried altering the registry key HKEY_CLASSES_ROOT\Applications\javaw.exe to add the value IsHostApp. This alters the behavior by disabling pinning of my application altogether; clearly not what I want.
After reading about how Windows interprets instances of a single application (and a phenomenon discussed in this question), I became interested in embedding a Application User Model ID (AppUserModelID) into my Java application.
I believe that I can resolve this by passing a unique AppUserModelID to Windows. There is a shell32 method for this, SetCurrentProcessExplicitAppUserModelID. Following Gregory Pakosz suggestion, I implemented it in an attempt to have my application recognized as a separate instance of javaw.exe:
NativeLibrary lib;
try {
lib = NativeLibrary.getInstance("shell32");
} catch (Error e) {
Logger.out.error("Could not load Shell32 library.");
return;
}
Object[] args = { "Vendor.MyJavaApplication" };
String functionName = "SetCurrentProcessExplicitAppUserModelID";
try {
Function function = lib.getFunction(functionName);
int ret = function.invokeInt(args);
if (ret != 0) {
Logger.out.error(function.getName() + " returned error code "
+ ret + ".");
}
} catch (UnsatisfiedLinkError e) {
Logger.out.error(functionName + " was not found in "
+ lib.getFile().getName() + ".");
// Function not supported
}
This appears to have no effect, but the function returns without error. Diagnosing why is something of a mystery to me. Any suggestions?
Working implementation
The final implementation that worked is the answer to my follow-up question concerning how to pass the AppID using JNA.
I had awarded the bounty to Gregory Pakosz' brilliant answer for JNI that set me on the right track.
For reference, I believe using this technique opens the possibility of using any of the APIs discussed in this article in a Java application.
I don't have Windows 7 but here is something that might get you started:
On the Java side:
package com.stackoverflow.homework;
public class MyApplication
{
static native boolean setAppUserModelID();
static
{
System.loadLibrary("MyApplicationJNI");
setAppUserModelID();
}
}
And on the native side, in the source code of the `MyApplicationJNI.dll library:
JNIEXPORT jboolean JNICALL Java_com_stackoverflow_homework_MyApplication_setAppUserModelID(JNIEnv* env)
{
LPCWSTR id = L"com.stackoverflow.homework.MyApplication";
HRESULT hr = SetCurrentProcessExplicitAppUserModelID(id);
return hr == S_OK;
}
Your question explicitly asked for a JNI solution. However, since your application doesn't need any other native method, jna is another solution which will save you from writing native code just for the sake of forwarding to the windows api. If you decide to go jna, pay attention to the fact that SetCurrentProcessExplicitAppUserModelID() is expecting a UTF-16 string.
When it works in your sandbox, the next step is to add operating system detection in your application as SetCurrentProcessExplicitAppUserModelID() is obviously only available in Windows 7:
you may do that from the Java side by checking that System.getProperty("os.name"); returns "Windows 7".
if you build from the little JNI snippet I gave, you can enhance it by dynamically loading the shell32.dll library using LoadLibrary then getting back the SetCurrentProcessExplicitAppUserModelID function pointer using GetProcAddress. If GetProcAddress returns NULL, it means the symbol is not present in shell32 hence it's not Windows 7.
EDIT: JNA Solution.
References:
The JNI book for more JNI examples
Java Native Access (JNA)
There is a Java library providing the new Windows 7 features for Java. It's called J7Goodies by Strix Code. Applications using it can be properly pinned to the Windows 7 taskbar. You can also create your own jump lists, etc.
I have implemented access to the SetCurrentProcessExplicitAppUserModelID method using JNA and it works quite well when used as the MSDN documentation suggests. I've never used the JNA api in the way you have in your code snippet. My implementation follows the typical JNA usage instead.
First the Shell32 interface definition:
interface Shell32 extends StdCallLibrary {
int SetCurrentProcessExplicitAppUserModelID( WString appID );
}
Then using JNA to load Shell32 and call the function:
final Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() {
{
put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
}
};
Shell32 shell32 = (Shell32) Native.loadLibrary("shell32", Shell32.class,
WIN32API_OPTIONS);
WString wAppId = new WString( "Vendor.MyJavaApplication" );
shell32.SetCurrentProcessExplicitAppUserModelID( wAppId );
Many of the API's in the last article you mentioned make use of Windows COM which is quite difficult to use directly with JNA. I have had some success creating a custom DLL to call these API's (eg. using the SHGetPropertyStoreForWindow to set a different app ID for a submodule window) which I then use JNA to access at runtime.
Try to use JSmooth. I use always this one. In JSmooth is there an option under Skeleton by Windowed Wrapper called
Lauch java app in exe process
See on this image.
(source: andrels.com)
Also command line arguments can be passed.
I think this can be a solution for you.
Martijn
SetCurrentProcessExplicitAppUserModelID (or SetAppID()) would in fact do what you're trying to do. However, it might be easier to modify your installer to set the AppUserModel.ID property on your shortcut - quoting from the Application User Model ID document mentioned above:
In the System.AppUserModel.ID property of the application's shortcut file. A shortcut (as an IShellLink, CLSID_ShellLink, or a .lnk file) supports properties through IPropertyStore and other property-setting mechanisms used throughout the Shell. This allows the taskbar to identify the proper shortcut to pin and ensures that windows belonging to the process are appropriately associated with that taskbar button.
Note: The System.AppUserModel.ID property should be applied to a shortcut when that shortcut is created. When using the Microsoft Windows Installer (MSI) to install the application, the MsiShortcutProperty table allows the AppUserModelID to be applied to the shortcut when it is created during installation.
The latest jna-platform library now includes JNA bindings for SetCurrentProcessExplicitAppUserModelID:
https://github.com/java-native-access/jna/pull/680
I fixed mine without any ID settings.
There is an option in Launch4J if you are using it and you say you do then...
You can change the header to JNI Gui and then wrap it around the jar with the JRE.
The good thing is that it runs .exe in the process now instead on running javaw.exe with your jar. It probably does it under the hood (not sure).
Also I have noticed also that it takes around 40-50% less CPU resource which is even better!
And the pinning works fine and all that window features are enabled.
I hope it helps to someone as I spent nearly 2 days trying to solve that issue with my undecorated javafx app.

Categories