Search code examples
javawindowsbatch-filecmdregedit

Changing value of registry key with getRuntime().exec(cmd) does not change registry value even the operation ended successfully


I'm trying to change registry value from my Java application. I use the command:

LoudnessEqualizationToggle.execCmdNoReturn("reg add \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\MMDevices\\Audio\\Render\\"+guid+"\\FxProperties\""
                                           + " /f /v \"{E0A941A0-88A2-4df5-8D6B-DD20BB06E8FB},4\" /t REG_DWORD /d \""+((activateLEOnKey) ? 1 : 0)+"\"");

Where guid is {d348b8e8-3118-4a9c-9b43-422647b555ca}

activateLEOnKey is boolean value

execCmdNoReturn function:

public static final void execCmdNoReturn(String cmd)  {

        try {
            Scanner s = new Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");

            System.out.println("Command:"+cmd);
            System.out.println("Printing executed data");

            while (s.hasNext()) {
                System.out.println(s.next());
            }
        } catch (IOException ex) {

            Logger.getLogger(LoudnessEqualizationToggle.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

Everything works okay. I get output into command prompt:

The operation completed successfully

So I start regedit to verify if value has changed, but to my surprise nothing changed. The value is the same as before.

Do I have permissions? Yes
I use a batch file to execute my application with Run as administrator.

Batch file:

cd %~dp0
java -jar LoudnessEqualizationToggle.jar
pause

Created shortcut from that and run as administrator.

Are you owner of that key? Yes

I tested my command and permissions with a batch file testing if the current value 0 in Windows registry can be changed to 1 as expected.

Batch file for that test is:

cd %~dp0
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render\{d348b8e8-3118-4a9c-9b43-422647b555ca}\FxProperties" /f /v "{E0A941A0-88A2-4df5-8D6B-DD20BB06E8FB},4" /t REG_DWORD /d "1"
net stop audiosrv //just restarting audio down here , not important
net stop AudioEndpointBuilder
net start audiosrv
net start AudioEndpointBuilder
pause

The value has changed in Windows registry after batch file execution from 0 to 1 (desired action).

So when I run my command from command prompt window directly, I can see the value changed. But when I run my command from runtime exec within my Java application, no value is changed in Windows registry, although I see that the command executed with no problem. And on my Java debug I see EXACTLY the same command being executed as I have in batch file.

What could be the reason for not getting the registry value changed by reg.exe command executed from within my Java application?

Process Monitor screen (after a tip by Mofi):

Process Monitor log with filter set to include all registry access with MMDevices in path


Solution

  • WOW6432Node in the log of Process Monitor indicates that the Java code is executed with 32-bit Java in a 32-bit environment on 64-bit Windows. Therefore the called reg.exe is also the 32-bit %SystemRoot%\SysWOW64\reg.exe which modifies therefore the DWORD value in WOW6432Node.

    Microsoft articles with details about Windows On Windows:

    One solution working for 32-bit and 64-bit Java on 32-bit and 64-bit Windows would be:

    1. Get string value of environment variable SystemRoot.

    2. Check if file SystemRoot + "\\Sysnative\\reg.exe" exists.

      This is only the case for 32-bit Java executed on 64-bit Windows. In all other cases, i.e. 64-bit Java on 64-bit Windows or 32-bit Java on 32-bit Windows, this file does not exist because Sysnative does not exist. Yes, Sysnative does not exist for 64-bit applications on 64-bit Windows.

    3. If the file reg.exe exists in Sysnative in Windows directory, call SystemRoot + "\\Sysnative\\reg.exe".

    4. Otherwise call SystemRoot + "\\System32\\reg.exe" which is the right executable for 64-bit Java on 64-bit Windows as well as 32-bit Java on 32-bit Windows.