Read/write to Windows registry using Java

前端 未结 24 1549
日久生厌
日久生厌 2020-11-21 05:45

How is it possible to read/write to the Windows registry using Java?

相关标签:
24条回答
  • 2020-11-21 06:10

    My previous edit to @David's answer was rejected. Here is some useful information about it.

    This "magic" works because Sun implements the Preferences class for Windows as part of JDK, but it is package private. Parts of the implementation use JNI.

    • Package private class from JDK java.util.prefs.WindowsPreferences: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/util/prefs/WindowsPreferences.java
    • JNI: http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/windows/native/java/util/WindowsPreferences.c

    The implementation is selected at runtime using a factory method here: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/util/prefs/Preferences.java#Preferences.0factory

    The real question: Why doesn't OpenJDK expose this API to public?

    0 讨论(0)
  • 2020-11-21 06:11

    Yes, using the java.util.Preferences API, since the Windows implementation of it uses the Registry as a backend.

    In the end it depends on what you're wanting to do: storing preferences for your app is what the Preferences does just great. If you're wanting to actually change registry keys not having to do with your app, you'll need some JNI app, as described by Mark (shameless steal here):

    From a quick google: Check the WinPack for JNIWrapper. It has full Windows Registry access support including Reading and Writing.

    The WinPack Demo has Registry Viewer implemented as an example.

    Check at http://www.teamdev.com/jniwrapper/winpack/#registry_access

    And...

    There is also try JNIRegistry @ http://www.trustice.com/java/jnireg/

    There is also the option of invoking an external app, which is responsible for reading / writing the registry.

    0 讨论(0)
  • 2020-11-21 06:11

    Although this is pretty old, but i guess the better utility to use on windows platform would be regini :

    A single call to process:

    Runtime.getRuntime().exec("regini <your script file abs path here>");
    

    will do all the magic. I have tried it, while making jar as windows service using servany.exe which requires changes to made in registry for adding javaw.exe arguments and it works perfectly. You might want to read this: http://support.microsoft.com/kb/264584

    0 讨论(0)
  • 2020-11-21 06:11

    This uses the same Java internal APIs as in in David's answer, but I've rewritten it completely. It's shorter now and nicer to use. I also added support for HKEY_CLASSES_ROOT and other hives. It still has some of the other limitations though (such as no DWORD support and no Unicode support) which are due to the underlying API and are sadly unavoidable with this approach. Still, if you only need basic string reading/writing and don't want to load a native DLL, it's handy.

    I'm sure you can figure out how to use it.

    Public domain. Have fun.

    import java.util.*;
    import java.lang.reflect.Method;
    
    /**
     * Simple registry access class implemented using some private APIs
     * in java.util.prefs. It has no other prerequisites.
     */
    public final class WindowsRegistry {
        /**
         * Tells if the Windows registry functions are available.
         * (They will not be available when not running on Windows, for example.)
         */
        public static boolean isAvailable() {
            return initError == null;
        }
    
    
    
        /** Reads a string value from the given key and value name. */
        public static String readValue(String keyName, String valueName) {
            try (Key key = Key.open(keyName, KEY_READ)) {
                return fromByteArray(invoke(regQueryValueEx, key.handle, toByteArray(valueName)));
            }
        }
    
    
    
        /** Returns a map of all the name-value pairs in the given key. */
        public static Map<String,String> readValues(String keyName) {
            try (Key key = Key.open(keyName, KEY_READ)) {
                int[] info = invoke(regQueryInfoKey, key.handle);
                checkError(info[INFO_ERROR_CODE]);
                int count = info[INFO_COUNT_VALUES];
                int maxlen = info[INFO_MAX_VALUE_LENGTH] + 1;
                Map<String,String> values = new HashMap<>();
                for (int i = 0; i < count; i++) {
                    String valueName = fromByteArray(invoke(regEnumValue, key.handle, i, maxlen));
                    values.put(valueName, readValue(keyName, valueName));
                }
                return values;
            }
        }
    
    
    
        /** Returns a list of the names of all the subkeys of a key. */
        public static List<String> readSubkeys(String keyName) {
            try (Key key = Key.open(keyName, KEY_READ)) {
                int[] info = invoke(regQueryInfoKey, key.handle);
                checkError(info[INFO_ERROR_CODE]);
                int count = info[INFO_COUNT_KEYS];
                int maxlen = info[INFO_MAX_KEY_LENGTH] + 1;
                List<String> subkeys = new ArrayList<>(count);
                for (int i = 0; i < count; i++) {
                    subkeys.add(fromByteArray(invoke(regEnumKeyEx, key.handle, i, maxlen)));
                }
                return subkeys;
            }
        }
    
    
    
        /** Writes a string value with a given key and value name. */
        public static void writeValue(String keyName, String valueName, String value) {
            try (Key key = Key.open(keyName, KEY_WRITE)) {
                checkError(invoke(regSetValueEx, key.handle, toByteArray(valueName), toByteArray(value)));
            }
        }
    
    
    
        /** Deletes a value within a key. */
        public static void deleteValue(String keyName, String valueName) {
            try (Key key = Key.open(keyName, KEY_WRITE)) {
                checkError(invoke(regDeleteValue, key.handle, toByteArray(valueName)));
            }
        }
    
    
    
        /**
         * Deletes a key and all values within it. If the key has subkeys, an
         * "Access denied" error will be thrown. Subkeys must be deleted separately.
         */
        public static void deleteKey(String keyName) {
            checkError(invoke(regDeleteKey, keyParts(keyName)));
        }
    
    
    
        /**
         * Creates a key. Parent keys in the path will also be created if necessary.
         * This method returns without error if the key already exists.
         */
        public static void createKey(String keyName) {
            int[] info = invoke(regCreateKeyEx, keyParts(keyName));
            checkError(info[INFO_ERROR_CODE]);
            invoke(regCloseKey, info[INFO_HANDLE]);
        }
    
    
    
        /**
         * The exception type that will be thrown if a registry operation fails.
         */
        public static class RegError extends RuntimeException {
            public RegError(String message, Throwable cause) {
                super(message, cause);
            }
        }
    
    
    
    
    
        // *************
        // PRIVATE STUFF
        // *************
    
        private WindowsRegistry() {}
    
    
        // Map of registry hive names to constants from winreg.h
        private static final Map<String,Integer> hives = new HashMap<>();
        static {
            hives.put("HKEY_CLASSES_ROOT",   0x80000000); hives.put("HKCR", 0x80000000);
            hives.put("HKEY_CURRENT_USER",   0x80000001); hives.put("HKCU", 0x80000001);
            hives.put("HKEY_LOCAL_MACHINE",  0x80000002); hives.put("HKLM", 0x80000002);
            hives.put("HKEY_USERS",          0x80000003); hives.put("HKU",  0x80000003);
            hives.put("HKEY_CURRENT_CONFIG", 0x80000005); hives.put("HKCC", 0x80000005);
        }
    
    
        // Splits a path such as HKEY_LOCAL_MACHINE\Software\Microsoft into a pair of
        // values used by the underlying API: An integer hive constant and a byte array
        // of the key path within that hive.
        private static Object[] keyParts(String fullKeyName) {
            int x = fullKeyName.indexOf('\\');
            String hiveName = x >= 0 ? fullKeyName.substring(0, x)  : fullKeyName;
            String keyName  = x >= 0 ? fullKeyName.substring(x + 1) : "";
            Integer hkey = hives.get(hiveName);
            if (hkey == null) throw new RegError("Unknown registry hive: " + hiveName, null);
            return new Object[] { hkey, toByteArray(keyName) };
        }
    
    
        // Type encapsulating a native handle to a registry key
        private static class Key implements AutoCloseable {
            final int handle;
    
            private Key(int handle) {
                this.handle = handle;
            }
    
            static Key open(String keyName, int accessMode) {
                Object[] keyParts = keyParts(keyName);
                int[] ret = invoke(regOpenKey, keyParts[0], keyParts[1], accessMode);
                checkError(ret[INFO_ERROR_CODE]);
                return new Key(ret[INFO_HANDLE]);
            }
    
            @Override
            public void close() {
                invoke(regCloseKey, handle);
            }
        }
    
    
        // Array index constants for results of regOpenKey, regCreateKeyEx, and regQueryInfoKey
        private static final int
            INFO_HANDLE = 0,
            INFO_COUNT_KEYS = 0,
            INFO_ERROR_CODE = 1,
            INFO_COUNT_VALUES = 2,
            INFO_MAX_KEY_LENGTH = 3,
            INFO_MAX_VALUE_LENGTH = 4;
    
    
        // Registry access mode constants from winnt.h
        private static final int
            KEY_READ = 0x20019,
            KEY_WRITE = 0x20006;
    
    
        // Error constants from winerror.h
        private static final int
            ERROR_SUCCESS = 0,
            ERROR_FILE_NOT_FOUND = 2,
            ERROR_ACCESS_DENIED = 5;
    
        private static void checkError(int e) {
            if (e == ERROR_SUCCESS) return;
            throw new RegError(
                e == ERROR_FILE_NOT_FOUND ? "Key not found" :
                e == ERROR_ACCESS_DENIED ? "Access denied" :
                ("Error number " + e), null);
        }
    
    
        // Registry access methods in java.util.prefs.WindowsPreferences
        private static final Method
            regOpenKey = getMethod("WindowsRegOpenKey", int.class, byte[].class, int.class),
            regCloseKey = getMethod("WindowsRegCloseKey", int.class),
            regQueryValueEx = getMethod("WindowsRegQueryValueEx", int.class, byte[].class),
            regQueryInfoKey = getMethod("WindowsRegQueryInfoKey", int.class),
            regEnumValue = getMethod("WindowsRegEnumValue", int.class, int.class, int.class),
            regEnumKeyEx = getMethod("WindowsRegEnumKeyEx", int.class, int.class, int.class),
            regSetValueEx = getMethod("WindowsRegSetValueEx", int.class, byte[].class, byte[].class),
            regDeleteValue = getMethod("WindowsRegDeleteValue", int.class, byte[].class),
            regDeleteKey = getMethod("WindowsRegDeleteKey", int.class, byte[].class),
            regCreateKeyEx = getMethod("WindowsRegCreateKeyEx", int.class, byte[].class);
    
        private static Throwable initError;
    
        private static Method getMethod(String methodName, Class<?>... parameterTypes) {
            try {
                Method m = java.util.prefs.Preferences.systemRoot().getClass()
                    .getDeclaredMethod(methodName, parameterTypes);
                m.setAccessible(true);
                return m;
            } catch (Throwable t) {
                initError = t;
                return null;
            }
        }
    
        @SuppressWarnings("unchecked")
        private static <T> T invoke(Method method, Object... args) {
            if (initError != null)
                throw new RegError("Registry methods are not available", initError);
            try {
                return (T)method.invoke(null, args);
            } catch (Exception e) {
                throw new RegError(null, e);
            }
        }
    
    
        // Conversion of strings to/from null-terminated byte arrays.
        // There is no support for Unicode; sorry, this is a limitation
        // of the underlying methods that Java makes available.
        private static byte[] toByteArray(String str) {
            byte[] bytes = new byte[str.length() + 1];
            for (int i = 0; i < str.length(); i++)
                bytes[i] = (byte)str.charAt(i);
            return bytes;
        }
    
        private static String fromByteArray(byte[] bytes) {
            if (bytes == null) return null;
            char[] chars = new char[bytes.length - 1];
            for (int i = 0; i < chars.length; i++)
                chars[i] = (char)((int)bytes[i] & 0xFF);
            return new String(chars);
        }
    }
    

    One day, Java will have a built-in foreign function interface for easy access to native APIs, and this sort of hack will be unnecessary.

    0 讨论(0)
  • 2020-11-21 06:12

    I've incremented the Pure java code originally posted by David to allow acessing the 32-bits section of the registry from a 64-bit JVM, and vice-versa. I don't think any of the other answers address this.

    Here it is:

    /**
     * Pure Java Windows Registry access.
     * Modified by petrucio@stackoverflow(828681) to add support for
     * reading (and writing but not creating/deleting keys) the 32-bits
     * registry view from a 64-bits JVM (KEY_WOW64_32KEY)
     * and 64-bits view from a 32-bits JVM (KEY_WOW64_64KEY).
     *****************************************************************************/
    
    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 int HKEY_CURRENT_USER = 0x80000001;
      public static final int 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;
    
      public static final int KEY_WOW64_32KEY = 0x0200;
      public static final int KEY_WOW64_64KEY = 0x0100;
    
      private static final int KEY_ALL_ACCESS = 0xf003f;
      private static final int KEY_READ = 0x20019;
      private static Preferences userRoot = Preferences.userRoot();
      private static Preferences systemRoot = Preferences.systemRoot();
      private static Class<? extends Preferences> userClass = userRoot.getClass();
      private static Method regOpenKey = null;
      private static Method regCloseKey = null;
      private static Method regQueryValueEx = null;
      private static Method regEnumValue = null;
      private static Method regQueryInfoKey = null;
      private static Method regEnumKeyEx = null;
      private static Method regCreateKeyEx = null;
      private static Method regSetValueEx = null;
      private static Method regDeleteKey = null;
      private static Method regDeleteValue = null;
    
      static {
        try {
          regOpenKey     = userClass.getDeclaredMethod("WindowsRegOpenKey",     new Class[] { int.class, byte[].class, int.class });
          regOpenKey.setAccessible(true);
          regCloseKey    = userClass.getDeclaredMethod("WindowsRegCloseKey",    new Class[] { int.class });
          regCloseKey.setAccessible(true);
          regQueryValueEx= userClass.getDeclaredMethod("WindowsRegQueryValueEx",new Class[] { int.class, byte[].class });
          regQueryValueEx.setAccessible(true);
          regEnumValue   = userClass.getDeclaredMethod("WindowsRegEnumValue",   new Class[] { int.class, int.class, int.class });
          regEnumValue.setAccessible(true);
          regQueryInfoKey=userClass.getDeclaredMethod("WindowsRegQueryInfoKey1",new Class[] { int.class });
          regQueryInfoKey.setAccessible(true);
          regEnumKeyEx   = userClass.getDeclaredMethod("WindowsRegEnumKeyEx",   new Class[] { int.class, int.class, int.class });  
          regEnumKeyEx.setAccessible(true);
          regCreateKeyEx = userClass.getDeclaredMethod("WindowsRegCreateKeyEx", new Class[] { int.class, byte[].class });
          regCreateKeyEx.setAccessible(true);  
          regSetValueEx  = userClass.getDeclaredMethod("WindowsRegSetValueEx",  new Class[] { int.class, byte[].class, byte[].class });  
          regSetValueEx.setAccessible(true); 
          regDeleteValue = userClass.getDeclaredMethod("WindowsRegDeleteValue", new Class[] { int.class, byte[].class });  
          regDeleteValue.setAccessible(true); 
          regDeleteKey   = userClass.getDeclaredMethod("WindowsRegDeleteKey",   new Class[] { int.class, byte[].class });  
          regDeleteKey.setAccessible(true); 
        }
        catch (Exception e) {
          e.printStackTrace();
        }
      }
    
      private WinRegistry() {  }
    
      /**
       * Read a value from key and value name
       * @param hkey   HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
       * @param key
       * @param valueName
       * @param wow64  0 for standard registry access (32-bits for 32-bit app, 64-bits for 64-bits app)
       *               or KEY_WOW64_32KEY to force access to 32-bit registry view,
       *               or KEY_WOW64_64KEY to force access to 64-bit registry view
       * @return the value
       * @throws IllegalArgumentException
       * @throws IllegalAccessException
       * @throws InvocationTargetException
       */
      public static String readString(int hkey, String key, String valueName, int wow64) 
        throws IllegalArgumentException, IllegalAccessException,
        InvocationTargetException 
      {
        if (hkey == HKEY_LOCAL_MACHINE) {
          return readString(systemRoot, hkey, key, valueName, wow64);
        }
        else if (hkey == HKEY_CURRENT_USER) {
          return readString(userRoot, hkey, key, valueName, wow64);
        }
        else {
          throw new IllegalArgumentException("hkey=" + hkey);
        }
      }
    
      /**
       * Read value(s) and value name(s) form given key 
       * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
       * @param key
       * @param wow64  0 for standard registry access (32-bits for 32-bit app, 64-bits for 64-bits app)
       *               or KEY_WOW64_32KEY to force access to 32-bit registry view,
       *               or KEY_WOW64_64KEY to force access to 64-bit registry view
       * @return the value name(s) plus the value(s)
       * @throws IllegalArgumentException
       * @throws IllegalAccessException
       * @throws InvocationTargetException
       */
      public static Map<String, String> readStringValues(int hkey, String key, int wow64) 
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        if (hkey == HKEY_LOCAL_MACHINE) {
          return readStringValues(systemRoot, hkey, key, wow64);
        }
        else if (hkey == HKEY_CURRENT_USER) {
          return readStringValues(userRoot, hkey, key, wow64);
        }
        else {
          throw new IllegalArgumentException("hkey=" + hkey);
        }
      }
    
      /**
       * Read the value name(s) from a given key
       * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
       * @param key
       * @param wow64  0 for standard registry access (32-bits for 32-bit app, 64-bits for 64-bits app)
       *               or KEY_WOW64_32KEY to force access to 32-bit registry view,
       *               or KEY_WOW64_64KEY to force access to 64-bit registry view
       * @return the value name(s)
       * @throws IllegalArgumentException
       * @throws IllegalAccessException
       * @throws InvocationTargetException
       */
      public static List<String> readStringSubKeys(int hkey, String key, int wow64) 
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        if (hkey == HKEY_LOCAL_MACHINE) {
          return readStringSubKeys(systemRoot, hkey, key, wow64);
        }
        else if (hkey == HKEY_CURRENT_USER) {
          return readStringSubKeys(userRoot, hkey, key, wow64);
        }
        else {
          throw new IllegalArgumentException("hkey=" + hkey);
        }
      }
    
      /**
       * Create a key
       * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
       * @param key
       * @throws IllegalArgumentException
       * @throws IllegalAccessException
       * @throws InvocationTargetException
       */
      public static void createKey(int hkey, String key) 
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        int [] ret;
        if (hkey == HKEY_LOCAL_MACHINE) {
          ret = createKey(systemRoot, hkey, key);
          regCloseKey.invoke(systemRoot, new Object[] { new Integer(ret[0]) });
        }
        else if (hkey == HKEY_CURRENT_USER) {
          ret = createKey(userRoot, hkey, key);
          regCloseKey.invoke(userRoot, new Object[] { new Integer(ret[0]) });
        }
        else {
          throw new IllegalArgumentException("hkey=" + hkey);
        }
        if (ret[1] != REG_SUCCESS) {
          throw new IllegalArgumentException("rc=" + ret[1] + "  key=" + key);
        }
      }
    
      /**
       * Write a value in a given key/value name
       * @param hkey
       * @param key
       * @param valueName
       * @param value
       * @param wow64  0 for standard registry access (32-bits for 32-bit app, 64-bits for 64-bits app)
       *               or KEY_WOW64_32KEY to force access to 32-bit registry view,
       *               or KEY_WOW64_64KEY to force access to 64-bit registry view
       * @throws IllegalArgumentException
       * @throws IllegalAccessException
       * @throws InvocationTargetException
       */
      public static void writeStringValue
        (int hkey, String key, String valueName, String value, int wow64) 
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        if (hkey == HKEY_LOCAL_MACHINE) {
          writeStringValue(systemRoot, hkey, key, valueName, value, wow64);
        }
        else if (hkey == HKEY_CURRENT_USER) {
          writeStringValue(userRoot, hkey, key, valueName, value, wow64);
        }
        else {
          throw new IllegalArgumentException("hkey=" + hkey);
        }
      }
    
      /**
       * Delete a given key
       * @param hkey
       * @param key
       * @throws IllegalArgumentException
       * @throws IllegalAccessException
       * @throws InvocationTargetException
       */
      public static void deleteKey(int hkey, String key) 
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        int rc = -1;
        if (hkey == HKEY_LOCAL_MACHINE) {
          rc = deleteKey(systemRoot, hkey, key);
        }
        else if (hkey == HKEY_CURRENT_USER) {
          rc = deleteKey(userRoot, hkey, key);
        }
        if (rc != REG_SUCCESS) {
          throw new IllegalArgumentException("rc=" + rc + "  key=" + key);
        }
      }
    
      /**
       * delete a value from a given key/value name
       * @param hkey
       * @param key
       * @param value
       * @param wow64  0 for standard registry access (32-bits for 32-bit app, 64-bits for 64-bits app)
       *               or KEY_WOW64_32KEY to force access to 32-bit registry view,
       *               or KEY_WOW64_64KEY to force access to 64-bit registry view
       * @throws IllegalArgumentException
       * @throws IllegalAccessException
       * @throws InvocationTargetException
       */
      public static void deleteValue(int hkey, String key, String value, int wow64) 
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        int rc = -1;
        if (hkey == HKEY_LOCAL_MACHINE) {
          rc = deleteValue(systemRoot, hkey, key, value, wow64);
        }
        else if (hkey == HKEY_CURRENT_USER) {
          rc = deleteValue(userRoot, hkey, key, value, wow64);
        }
        if (rc != REG_SUCCESS) {
          throw new IllegalArgumentException("rc=" + rc + "  key=" + key + "  value=" + value);
        }
      }
    
      //========================================================================
      private static int deleteValue(Preferences root, int hkey, String key, String value, int wow64)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
            new Integer(hkey), toCstr(key), new Integer(KEY_ALL_ACCESS | wow64)
        });
        if (handles[1] != REG_SUCCESS) {
          return handles[1];  // can be REG_NOTFOUND, REG_ACCESSDENIED
        }
        int rc =((Integer) regDeleteValue.invoke(root, new Object[] { 
              new Integer(handles[0]), toCstr(value) 
              })).intValue();
        regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
        return rc;
      }
    
      //========================================================================
      private static int deleteKey(Preferences root, int hkey, String key) 
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        int rc =((Integer) regDeleteKey.invoke(root, new Object[] {
            new Integer(hkey), toCstr(key)
        })).intValue();
        return rc;  // can REG_NOTFOUND, REG_ACCESSDENIED, REG_SUCCESS
      }
    
      //========================================================================
      private static String readString(Preferences root, int hkey, String key, String value, int wow64)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
            new Integer(hkey), toCstr(key), new Integer(KEY_READ | wow64)
        });
        if (handles[1] != REG_SUCCESS) {
          return null; 
        }
        byte[] valb = (byte[]) regQueryValueEx.invoke(root, new Object[] {
            new Integer(handles[0]), toCstr(value)
        });
        regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
        return (valb != null ? new String(valb).trim() : null);
      }
    
      //========================================================================
      private static Map<String,String> readStringValues(Preferences root, int hkey, String key, int wow64)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        HashMap<String, String> results = new HashMap<String,String>();
        int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
            new Integer(hkey), toCstr(key), new Integer(KEY_READ | wow64)
        });
        if (handles[1] != REG_SUCCESS) {
          return null;
        }
        int[] info = (int[]) regQueryInfoKey.invoke(root, new Object[] {
            new Integer(handles[0])
        });
    
        int count  = info[2]; // count  
        int maxlen = info[3]; // value length max
        for(int index=0; index<count; index++)  {
          byte[] name = (byte[]) regEnumValue.invoke(root, new Object[] {
              new Integer(handles[0]), new Integer(index), new Integer(maxlen + 1)
          });
          String value = readString(hkey, key, new String(name), wow64);
          results.put(new String(name).trim(), value);
        }
        regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
        return results;
      }
    
      //========================================================================
      private static List<String> readStringSubKeys(Preferences root, int hkey, String key, int wow64)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        List<String> results = new ArrayList<String>();
        int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
            new Integer(hkey), toCstr(key), new Integer(KEY_READ | wow64) 
            });
        if (handles[1] != REG_SUCCESS) {
          return null;
        }
        int[] info = (int[]) regQueryInfoKey.invoke(root, new Object[] {
            new Integer(handles[0])
        });
    
        int count  = info[0]; // Fix: info[2] was being used here with wrong results. Suggested by davenpcj, confirmed by Petrucio
        int maxlen = info[3]; // value length max
        for(int index=0; index<count; index++)  {
          byte[] name = (byte[]) regEnumKeyEx.invoke(root, new Object[] {
              new Integer(handles[0]), new Integer(index), new Integer(maxlen + 1)
              });
          results.add(new String(name).trim());
        }
        regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
        return results;
      }
    
      //========================================================================
      private static int [] createKey(Preferences root, int hkey, String key)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        return (int[]) regCreateKeyEx.invoke(root, new Object[] {
          new Integer(hkey), toCstr(key)
        });
      }
    
      //========================================================================
      private static void writeStringValue(Preferences root, int hkey, String key, String valueName, String value, int wow64)
        throws IllegalArgumentException, IllegalAccessException, InvocationTargetException 
      {
        int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
            new Integer(hkey), toCstr(key), new Integer(KEY_ALL_ACCESS | wow64)
        });
        regSetValueEx.invoke(root, new Object[] { 
              new Integer(handles[0]), toCstr(valueName), toCstr(value) 
              }); 
        regCloseKey.invoke(root, new Object[] { new Integer(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;
      }
    }
    
    0 讨论(0)
  • 2020-11-21 06:15

    In response to David answer - I would do some enhancements:

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import java.util.prefs.Preferences;
    
    public class WinRegistry {
    
        public static final int HKEY_CURRENT_USER = 0x80000001,
                HKEY_LOCAL_MACHINE = 0x80000002,
                REG_SUCCESS = 0,
                REG_NOTFOUND = 2,
                REG_ACCESSDENIED = 5,
                KEY_ALL_ACCESS = 0xf003f,
                KEY_READ = 0x20019;
        private static final Preferences userRoot = Preferences.userRoot(),
                systemRoot = Preferences.systemRoot();
        private static final Class<? extends Preferences> userClass = userRoot.getClass();
        private static Method regOpenKey,
                regCloseKey,
                regQueryValueEx,
                regEnumValue,
                regQueryInfoKey,
                regEnumKeyEx,
                regCreateKeyEx,
                regSetValueEx,
                regDeleteKey,
                regDeleteValue;
    
        static {
            try {
                (regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey", new Class[]{int.class, byte[].class, int.class})).setAccessible(true);
                (regCloseKey = userClass.getDeclaredMethod("WindowsRegCloseKey", new Class[]{int.class})).setAccessible(true);
                (regQueryValueEx = userClass.getDeclaredMethod("WindowsRegQueryValueEx", new Class[]{int.class, byte[].class})).setAccessible(true);
                (regEnumValue = userClass.getDeclaredMethod("WindowsRegEnumValue", new Class[]{int.class, int.class, int.class})).setAccessible(true);
                (regQueryInfoKey = userClass.getDeclaredMethod("WindowsRegQueryInfoKey1", new Class[]{int.class})).setAccessible(true);
                (regEnumKeyEx = userClass.getDeclaredMethod("WindowsRegEnumKeyEx", new Class[]{int.class, int.class, int.class})).setAccessible(true);
                (regCreateKeyEx = userClass.getDeclaredMethod("WindowsRegCreateKeyEx", new Class[]{int.class, byte[].class})).setAccessible(true);
                (regSetValueEx = userClass.getDeclaredMethod("WindowsRegSetValueEx", new Class[]{int.class, byte[].class, byte[].class})).setAccessible(true);
                (regDeleteValue = userClass.getDeclaredMethod("WindowsRegDeleteValue", new Class[]{int.class, byte[].class})).setAccessible(true);
                (regDeleteKey = userClass.getDeclaredMethod("WindowsRegDeleteKey", new Class[]{int.class, byte[].class})).setAccessible(true);
            } catch (NoSuchMethodException | SecurityException ex) {
                Logger.getLogger(WinRegistry.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    
        /**
         * Read a value from key and value name
         *
         * @param hkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
         * @param key
         * @param valueName
         * @return the value
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         */
        public static String readString(int hkey, String key, String valueName) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            switch (hkey) {
                case HKEY_LOCAL_MACHINE:
                    return readString(systemRoot, hkey, key, valueName);
                case HKEY_CURRENT_USER:
                    return readString(userRoot, hkey, key, valueName);
                default:
                    throw new IllegalArgumentException("hkey=" + hkey);
            }
        }
    
        /**
         * Read value(s) and value name(s) form given key
         *
         * @param hkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
         * @param key
         * @return the value name(s) plus the value(s)
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         */
        public static Map<String, String> readStringValues(int hkey, String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            switch (hkey) {
                case HKEY_LOCAL_MACHINE:
                    return readStringValues(systemRoot, hkey, key);
                case HKEY_CURRENT_USER:
                    return readStringValues(userRoot, hkey, key);
                default:
                    throw new IllegalArgumentException("hkey=" + hkey);
            }
        }
    
        /**
         * Read the value name(s) from a given key
         *
         * @param hkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
         * @param key
         * @return the value name(s)
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         */
        public static List<String> readStringSubKeys(int hkey, String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            switch (hkey) {
                case HKEY_LOCAL_MACHINE:
                    return readStringSubKeys(systemRoot, hkey, key);
                case HKEY_CURRENT_USER:
                    return readStringSubKeys(userRoot, hkey, key);
                default:
                    throw new IllegalArgumentException("hkey=" + hkey);
            }
        }
    
        /**
         * Create a key
         *
         * @param hkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
         * @param key
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         */
        public static void createKey(int hkey, String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            int[] ret;
            switch (hkey) {
                case HKEY_LOCAL_MACHINE:
                    ret = createKey(systemRoot, hkey, key);
                    regCloseKey.invoke(systemRoot, new Object[]{ret[0]});
                    break;
                case HKEY_CURRENT_USER:
                    ret = createKey(userRoot, hkey, key);
                    regCloseKey.invoke(userRoot, new Object[]{ret[0]});
                    break;
                default:
                    throw new IllegalArgumentException("hkey=" + hkey);
            }
    
            if (ret[1] != REG_SUCCESS) {
                throw new IllegalArgumentException("rc=" + ret[1] + " key=" + key);
            }
        }
    
        /**
         * Write a value in a given key/value name
         *
         * @param hkey
         * @param key
         * @param valueName
         * @param value
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         */
        public static void writeStringValue(int hkey, String key, String valueName, String value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            switch (hkey) {
                case HKEY_LOCAL_MACHINE:
                    writeStringValue(systemRoot, hkey, key, valueName, value);
                    break;
                case HKEY_CURRENT_USER:
                    writeStringValue(userRoot, hkey, key, valueName, value);
                    break;
                default:
                    throw new IllegalArgumentException("hkey=" + hkey);
            }
        }
    
        /**
         * Delete a given key
         *
         * @param hkey
         * @param key
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         */
        public static void deleteKey(int hkey, String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            int rc = -1;
            switch (hkey) {
                case HKEY_LOCAL_MACHINE:
                    rc = deleteKey(systemRoot, hkey, key);
                    break;
                case HKEY_CURRENT_USER:
                    rc = deleteKey(userRoot, hkey, key);
            }
    
            if (rc != REG_SUCCESS) {
                throw new IllegalArgumentException("rc=" + rc + " key=" + key);
            }
        }
    
        /**
         * delete a value from a given key/value name
         *
         * @param hkey
         * @param key
         * @param value
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         */
        public static void deleteValue(int hkey, String key, String value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            int rc = -1;
            switch (hkey) {
                case HKEY_LOCAL_MACHINE:
                    rc = deleteValue(systemRoot, hkey, key, value);
                    break;
                case HKEY_CURRENT_USER:
                    rc = deleteValue(userRoot, hkey, key, value);
            }
    
            if (rc != REG_SUCCESS) {
                throw new IllegalArgumentException("rc=" + rc + " key=" + key + " value=" + value);
            }
        }
    
        private static int deleteValue(Preferences root, int hkey, String key, String value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            int[] handles = (int[]) regOpenKey.invoke(root, new Object[]{hkey, toCstr(key), KEY_ALL_ACCESS});
            if (handles[1] != REG_SUCCESS) {
                return handles[1];//Can be REG_NOTFOUND, REG_ACCESSDENIED
            }
            int rc = ((Integer) regDeleteValue.invoke(root, new Object[]{handles[0], toCstr(value)}));
            regCloseKey.invoke(root, new Object[]{handles[0]});
            return rc;
        }
    
        private static int deleteKey(Preferences root, int hkey, String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            int rc = ((Integer) regDeleteKey.invoke(root, new Object[]{hkey, toCstr(key)}));
            return rc;  //Can be REG_NOTFOUND, REG_ACCESSDENIED, REG_SUCCESS
        }
    
        private static String readString(Preferences root, int hkey, String key, String value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            int[] handles = (int[]) regOpenKey.invoke(root, new Object[]{hkey, toCstr(key), KEY_READ});
            if (handles[1] != REG_SUCCESS) {
                return null;
            }
            byte[] valb = (byte[]) regQueryValueEx.invoke(root, new Object[]{handles[0], toCstr(value)});
            regCloseKey.invoke(root, new Object[]{handles[0]});
            return (valb != null ? new String(valb).trim() : null);
        }
    
        private static Map<String, String> readStringValues(Preferences root, int hkey, String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            HashMap<String, String> results = new HashMap<>();
            int[] handles = (int[]) regOpenKey.invoke(root, new Object[]{hkey, toCstr(key), KEY_READ});
            if (handles[1] != REG_SUCCESS) {
                return null;
            }
            int[] info = (int[]) regQueryInfoKey.invoke(root, new Object[]{handles[0]});
    
            int count = info[0]; //Count  
            int maxlen = info[3]; //Max value length
            for (int index = 0; index < count; index++) {
                byte[] name = (byte[]) regEnumValue.invoke(root, new Object[]{handles[0], index, maxlen + 1});
                String value = readString(hkey, key, new String(name));
                results.put(new String(name).trim(), value);
            }
            regCloseKey.invoke(root, new Object[]{handles[0]});
            return results;
        }
    
        private static List<String> readStringSubKeys(Preferences root, int hkey, String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            List<String> results = new ArrayList<>();
            int[] handles = (int[]) regOpenKey.invoke(root, new Object[]{hkey, toCstr(key), KEY_READ});
            if (handles[1] != REG_SUCCESS) {
                return null;
            }
            int[] info = (int[]) regQueryInfoKey.invoke(root, new Object[]{handles[0]});
    
            int count = info[0];//Count
            int maxlen = info[3]; //Max value length
            for (int index = 0; index < count; index++) {
                byte[] name = (byte[]) regEnumKeyEx.invoke(root, new Object[]{handles[0], index, maxlen + 1});
                results.add(new String(name).trim());
            }
            regCloseKey.invoke(root, new Object[]{handles[0]});
            return results;
        }
    
        private static int[] createKey(Preferences root, int hkey, String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            return (int[]) regCreateKeyEx.invoke(root, new Object[]{hkey, toCstr(key)});
        }
    
        private static void writeStringValue(Preferences root, int hkey, String key, String valueName, String value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    
            int[] handles = (int[]) regOpenKey.invoke(root, new Object[]{hkey, toCstr(key), KEY_ALL_ACCESS});
            regSetValueEx.invoke(root, new Object[]{handles[0], toCstr(valueName), toCstr(value)});
            regCloseKey.invoke(root, new Object[]{handles[0]});
        }
    
        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;
        }
    }
    
    0 讨论(0)
提交回复
热议问题