# WinRegistry not working anymore in Processing 4

**URL:** https://discourse.processing.org/t/winregistry-not-working-anymore-in-processing-4/40258
**Category:** Coding Questions
**Created:** [December 22, 2022, 2:36am UTC](https://discourse.processing.org/t/winregistry-not-working-anymore-in-processing-4/40258 "2022-12-22T02:36:28Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![Martin\_The\_Sun](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/martin_the_sun/32/17660_2.png) [@Martin\_The\_Sun](https://discourse.processing.org/u/Martin_The_Sun)
#### Post date: [December 22, 2022, 2:36am UTC](https://discourse.processing.org/t/winregistry-not-working-anymore-in-processing-4/40258/1 "2022-12-22T02:36:28Z")

</div>

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](https://stackoverflow.com/questions/65630568/java-error-java-util-prefs-windowspreferences-windowsregopenkey) 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”);

---

<div class="post-metadata">

### Author: ![mnse](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mnse/32/16520_2.png) [@mnse](https://discourse.processing.org/u/mnse)
#### Post date: [December 22, 2022, 8:53am UTC](https://discourse.processing.org/t/winregistry-not-working-anymore-in-processing-4/40258/2 "2022-12-22T08:53:09Z")

</div>

Hi @Martin_The_Sun,

this is not a processing issue, but rather a jdk one, as the reflection handling has changed.  
As the error message says, it is (by default) not allowed anymore, hence …

```auto
InaccessibleObjectException: Unable to make private static ... accessible.

```

Maybe you can read here about the background …

[https://openjdk.org/jeps/396](https://openjdk.org/jeps/396)  
[https://openjdk.org/jeps/403](https://openjdk.org/jeps/403)

Cheers  
— mnse

---

<div class="post-metadata">

### Author: ![mnse](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mnse/32/16520_2.png) [@mnse](https://discourse.processing.org/u/mnse)
#### Post date: [December 22, 2022, 10:10am UTC](https://discourse.processing.org/t/winregistry-not-working-anymore-in-processing-4/40258/3 "2022-12-22T10:10:08Z")

</div>

Hi @Martin_The_Sun,

on your own risk you can change the `run.options=` of your preferences.txt file.

`run.options=--add-opens java.prefs/java.util.prefs=ALL-UNNAMED`

this will allow you to bypass the restrictions …

Cheers  
—mnse

---

<div class="post-metadata">

### Author: ![Martin\_The\_Sun](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/martin_the_sun/32/17660_2.png) [@Martin\_The\_Sun](https://discourse.processing.org/u/Martin_The_Sun)
#### Post date: [December 23, 2022, 3:28am UTC](https://discourse.processing.org/t/winregistry-not-working-anymore-in-processing-4/40258/4 "2022-12-23T03:28:45Z")

</div>

Hi @mnse , thanks so much for your suggestion. I tried adding the code

> `run.options=--add-opens java.prefs/java.util.prefs=ALL-UNNAMED`

in preferences.txt. Yes, it works and Processing bypasses the error and key registration can be done in regedit.

Unfortunately, if I export my processing program as application (i.e. .exe file) and run it. I found that the app stops running in the step of initializing an instance of WinRegistry, i.e. this step:

> WinRegistry W = new WinRegistry();

Besides, regedit has no any path update so i confirm that key registration is not done. Since i don’t know how to trace the program flow inside java code when running the app, I don’t know where the problem is, but i suspect that the handling problem still restrict the operation when the program is exported as app.

Apart from bypassing the error, i wonder if there is other approaches we can do to modify the codes in WinRegistry directly to adapt the new change in JDK?

---

<div class="post-metadata">

### Author: ![mnse](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mnse/32/16520_2.png) [@mnse](https://discourse.processing.org/u/mnse)
#### Post date: [December 23, 2022, 8:50am UTC](https://discourse.processing.org/t/winregistry-not-working-anymore-in-processing-4/40258/5 "2022-12-23T08:50:50Z")

</div>

Hi @Martin_The_Sun,

> [@Martin\_The\_Sun](#):
>
> Unfortunately, if I export my processing program as application (i.e. .exe file) and run it. I found that the app stops running in the step of initializing an instance of WinRegistry, i.e. this step:

Sorry! Too long to explain all the background information, but …  
…you need to create an additional configuration file beside your executable which let it know that you want to use an additional parameter for execution. It must be in the same directory as you executable!

- go to the directory where you have your executable.
- assuming you exe is called: **myapp.exe**
- Create a file named: **myapp.l4j.ini**
- content of the file should be in your case a single line with the required option  
**`--add-opens java.prefs/java.util.prefs=ALL-UNNAMED`**
- save the ini file.
- Afterwards you can run the exe and it would/should work. 🙂

* * *

> [@Martin\_The\_Sun](#):
>
> Apart from bypassing the error, i wonder if there is other approaches we can do to modify the codes in WinRegistry directly to adapt the new change in JDK?

There are several approaches but none of them are really, let’s say, the holy grail, but rather work-arounds to the issue.

Cheers  
— mnse

---

<div class="post-metadata">

### Author: ![Martin\_The\_Sun](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/martin_the_sun/32/17660_2.png) [@Martin\_The\_Sun](https://discourse.processing.org/u/Martin_The_Sun)
#### Post date: [December 23, 2022, 9:53am UTC](https://discourse.processing.org/t/winregistry-not-working-anymore-in-processing-4/40258/6 "2022-12-23T09:53:25Z")

</div>

Hi @mnse ,

oh yes, it works for .exe now after i prepared that ini file. Many thanks to your help.

just a minor question, isn’t it possible to hide this ini fle in a subfolder instead of putting it next to my exe file? Right now the ini file is just next to my exe file in my software directory and i am afraid user will feel a litter bit confused to click the exe file since both files has similar filename.

For example, moving the ini file to a subfolder ‘ini’ (or whatever name) and my exe file can still refer to that ini when it is executed. Is this possible?

![query](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/4/4/441b61f14b711b582786d8ee0ae226016452024d.jpeg)

---

<div class="post-metadata">

### Author: ![mnse](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mnse/32/16520_2.png) [@mnse](https://discourse.processing.org/u/mnse)
#### Post date: [December 23, 2022, 11:16am UTC](https://discourse.processing.org/t/winregistry-not-working-anymore-in-processing-4/40258/7 "2022-12-23T11:16:55Z")

</div>

Hi @Martin_The_Sun,

No! It is not possible to move the ini file to a different location as the process searches it next to the exe file, resp. in the directory of the exe file. Also the naming convention can’t be changed.  
The process simple uses the exe path, remove the .exe extension apply the .l4j.ini and search for it.

There are more advanced things you can do, but for that you need to patch the exe itself by ie. a resource hacking tool.

Cheers  
— mnse

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [December 23, 2022, 12:37pm UTC](https://discourse.processing.org/t/winregistry-not-working-anymore-in-processing-4/40258/8 "2022-12-23T12:37:08Z")

</div>

> [@Martin\_The\_Sun](#):
>
> Right now the “.ini” file is just next to my “.exe” file in my software directory and I am afraid the user will feel a little bit confused to click the “.exe” file since both files have similar filenames.

You can “hide” the file via the `attrib` command-line:  
attrib +h +s +r \*.ini

> **[How to Use the Attrib Command in Windows](https://www.lifewire.com/attrib-command-2625802)**
>
> Learn about the attrib command, available from Command Prompt and MS-DOS, that's used to view or change file attributes for a file or folder.

---

<div class="post-metadata">

### Author: ![Martin\_The\_Sun](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/martin_the_sun/32/17660_2.png) [@Martin\_The\_Sun](https://discourse.processing.org/u/Martin_The_Sun)
#### Post date: [December 25, 2022, 6:16am UTC](https://discourse.processing.org/t/winregistry-not-working-anymore-in-processing-4/40258/9 "2022-12-25T06:16:23Z")

</div>

@GoToLoop , yes, this is a good suggestion, will consider this approach, thanks!  
@mnse , just one more question. If I bypass the error checking for java.util.prefs, potentially what kinds of risks I might come across? I would like to have an idea so that I can be more well-prepared in the future of developing the software.

---

<div class="post-metadata">

### Author: ![mnse](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mnse/32/16520_2.png) [@mnse](https://discourse.processing.org/u/mnse)
#### Post date: [December 25, 2022, 7:50am UTC](https://discourse.processing.org/t/winregistry-not-working-anymore-in-processing-4/40258/10 "2022-12-25T07:50:09Z")

</div>

Hi @Martin_The_Sun,

Imo, actually none! The background of all is that jep 403 makes the whole jdk more secure, resp. more specific in case of using reflection. Before it all was permitted by default without let the user know that it is used internally. Now you have to declare and allow it explicitly if you want to use.

Cheers  
— mnse
