I was using java code to do file association for my software in Window platform. The class is called WinRegistry which can be commonly found online. The code worked well when I develop my software in Processing 3.5.4 but fails to work when i migrate my system to Processing 4.1.1
From here: regedit - JAVA : ERROR Java.util.prefs.WindowsPreferences.WindowsRegOpenKey - Stack Overflow I know that I should change some data type from int to long to adapt the change of JDK. I did so, like this:
regOpenKey = userClass.getDeclaredMethod(âWindowsRegOpenKeyâ, new Class[ ] { long.class, byte[ ].class, int.class });
regOpenKey.setAccessible(true);
I also adjusted the rest of the code accordingly. However it still did not work and the error message is:
RuntimeException: java.lang.reflect.InaccessibleObjectException: Unable to make private static native long[ ] java.util.prefs.WindowsPreferences.WindowsRegOpenKey(long,byte[ ],int) accessible: module java.prefs does not âopens java.util.prefsâ to unnamed module @2a22d168
Since I develop my software in Processing so I suppose the way to solve this problem depends on Processing rather than by Java. Is it because of the upgrade of JDK in Processing 4? I have TOTALLY no idea how to handle this. Can anyone help please? The full code of WinRegistry is here:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import java.util.List;
import java.util.prefs.Preferences;public class WinRegistry
{
public static final long HKEY_CURRENT_USER = 0x80000001;
public static final long HKEY_LOCAL_MACHINE = 0x80000002;
public static final int REG_SUCCESS = 0;
public static final int REG_NOTFOUND = 2;
public static final int REG_ACCESSDENIED = 5;
private static final int KEY_ALL_ACCESS = 0xf003f;
private static final int KEY_READ = 0x20019;
private static final Preferences userRoot = Preferences.userRoot();
private static final Preferences systemRoot = Preferences.systemRoot();
private static final Class<? extends Preferences> userClass = userRoot.getClass();
private static final Method regOpenKey;
private static final Method regCloseKey;
private static final Method regQueryValueEx;
private static final Method regEnumValue;
private static final Method regQueryInfoKey;
private static final Method regEnumKeyEx;
private static final Method regCreateKeyEx;
private static final Method regSetValueEx;static {
try { regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey", new Class[] { long.class, byte[].class, int.class }); regOpenKey.setAccessible(true); regCloseKey = userClass.getDeclaredMethod("WindowsRegCloseKey", new Class[] { long.class }); regCloseKey.setAccessible(true); regQueryValueEx = userClass.getDeclaredMethod("WindowsRegQueryValueEx", new Class[] { long.class, byte[].class }); regQueryValueEx.setAccessible(true); regEnumValue = userClass.getDeclaredMethod("WindowsRegEnumValue", new Class[] { long.class, int.class, int.class }); regEnumValue.setAccessible(true); regQueryInfoKey = userClass.getDeclaredMethod("WindowsRegQueryInfoKey1", new Class[] { long.class }); regQueryInfoKey.setAccessible(true); regEnumKeyEx = userClass.getDeclaredMethod("WindowsRegEnumKeyEx", new Class[] { long.class, int.class, int.class }); regEnumKeyEx.setAccessible(true); regCreateKeyEx = userClass.getDeclaredMethod( "WindowsRegCreateKeyEx", new Class[] { long.class, byte[].class }); regCreateKeyEx.setAccessible(true); regSetValueEx = userClass.getDeclaredMethod( "WindowsRegSetValueEx", new Class[] { long.class, byte[].class, byte[].class }); regSetValueEx.setAccessible(true); } catch (Exception e) { throw new RuntimeException(e); } } WinRegistry() { } public static void createKey(long hkey, String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { long [] ret; if (hkey == HKEY_LOCAL_MACHINE) { ret = createKey(systemRoot, hkey, key); regCloseKey.invoke(systemRoot, new Object[] { ret[0] }); } else if (hkey == HKEY_CURRENT_USER) { ret = createKey(userRoot, hkey, key); regCloseKey.invoke(userRoot, new Object[] { ret[0] }); } else { throw new IllegalArgumentException("hkey=" + hkey); } if (ret[1] != REG_SUCCESS) { throw new IllegalArgumentException("rc=" + ret[1] + " key=" + key); } } public static void writeStringValue (long hkey, String key, String valueName, String value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { if (hkey == HKEY_LOCAL_MACHINE) writeStringValue(systemRoot, hkey, key, valueName, value); else if (hkey == HKEY_CURRENT_USER) writeStringValue(userRoot, hkey, key, valueName, value); else throw new IllegalArgumentException("hkey=" + hkey); } private static long [] createKey(Preferences root, long hkey, String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { return (long[]) regCreateKeyEx.invoke(root, new Object[] { hkey, toCstr(key) }); } private static void writeStringValue (Preferences root, long hkey, String key, String valueName, String value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { long[] handles = (long[]) regOpenKey.invoke(root, new Object[] { hkey, toCstr(key), new Integer(KEY_ALL_ACCESS) }); // is here the problem??? regSetValueEx.invoke(root, new Object[] { handles[0], toCstr(valueName), toCstr(value) }); regCloseKey.invoke(root, new Object[] { handles[0] }); } // utility private static byte[] toCstr(String str) { byte[] result = new byte[str.length() + 1]; for (int i = 0; i < str.length(); i++) { result[i] = (byte) str.charAt(i); } result[str.length()] = 0; return result; } }
And the way to execute WinRegistry is something like this, assuming the extension of the file is â.abcâ and the ProgramID is âabc_Fileâ:
WinRegistry W = new WinRegistry();
W.createKey(W.HKEY_CURRENT_USER, âSoftware\Classes\.abcâ);
W.writeStringValue(W.HKEY_CURRENT_USER, âSoftware\Classes\.abcâ, ââ, âabc_Fileâ);