Read/write to Windows registry using Java

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

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

24条回答
  •  长发绾君心
    2020-11-21 06:20

    Thanks to original post. I have reskinned this utility class and come up over the flaws which it had earlier, thought it might help others so posting here. I have also added some extra utility methods. Now it is able to read any file in windows registry(including REG_DWORD, REG_BINARY, REG_EXPAND_SZ etc.). All the methods work like a charm. Just copy and paste it and it should work. Here is the reskinned and modified class:

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    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.StringTokenizer;
    import java.util.prefs.Preferences;
    
    public class WinRegistry {
    
        private static final int REG_SUCCESS = 0;
        private static final int REG_NOTFOUND = 2;
        private static final int KEY_READ = 0x20019;
        private static final int REG_ACCESSDENIED = 5;
        private static final int KEY_ALL_ACCESS = 0xf003f;
        public static final int HKEY_CLASSES_ROOT = 0x80000000;
        public static final int HKEY_CURRENT_USER = 0x80000001;
        public static final int HKEY_LOCAL_MACHINE = 0x80000002;
        private static final String CLASSES_ROOT = "HKEY_CLASSES_ROOT";
        private static final String CURRENT_USER = "HKEY_CURRENT_USER";
        private static final String LOCAL_MACHINE = "HKEY_LOCAL_MACHINE";
        private static Preferences userRoot = Preferences.userRoot();
        private static Preferences systemRoot = Preferences.systemRoot();
        private static Class 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();
            }
        }
    
        /**
         * Reads value for the key from given path
         * @param hkey   HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
         * @param path
         * @param key
         * @return the value
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         * @throws IOException 
         */
        public static String valueForKey(int hkey, String path, String key) 
                throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {
            if (hkey == HKEY_LOCAL_MACHINE)
                return valueForKey(systemRoot, hkey, path, key);
            else if (hkey == HKEY_CURRENT_USER)
                return valueForKey(userRoot, hkey, path, key);
            else
                return valueForKey(null, hkey, path, key);
        }
    
        /**
         * Reads all key(s) and value(s) from given path
         * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
         * @param path
         * @return the map of key(s) and corresponding value(s)
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         * @throws IOException 
         */
        public static Map valuesForPath(int hkey, String path) 
                throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {
            if (hkey == HKEY_LOCAL_MACHINE)
                return valuesForPath(systemRoot, hkey, path);
            else if (hkey == HKEY_CURRENT_USER)
                return valuesForPath(userRoot, hkey, path);
            else
                return valuesForPath(null, hkey, path);
        }
    
        /**
         * Read all the subkey(s) from a given path
         * @param hkey  HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
         * @param path
         * @return the subkey(s) list
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         */
        public static List subKeysForPath(int hkey, String path)
                throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
            if (hkey == HKEY_LOCAL_MACHINE)
                return subKeysForPath(systemRoot, hkey, path);
            else if (hkey == HKEY_CURRENT_USER)
                return subKeysForPath(userRoot, hkey, path);
            else
                return subKeysForPath(null, hkey, path);
        }
    
        /**
         * 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
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         */
        public static void writeStringValue(int 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);
        }
    
        /**
         * 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
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         */
        public static void deleteValue(int hkey, String key, String value) 
                throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
            int rc = -1;
            if (hkey == HKEY_LOCAL_MACHINE)
                rc = deleteValue(systemRoot, hkey, key, value);
            else if (hkey == 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[] {new Integer(hkey), toCstr(key), new Integer(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[] {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 valueForKey(Preferences root, int hkey, String path, String key)
                throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {
            int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {new Integer(hkey), toCstr(path), new Integer(KEY_READ)});
            if (handles[1] != REG_SUCCESS)
                throw new IllegalArgumentException("The system can not find the specified path: '"+getParentKey(hkey)+"\\"+path+"'");
            byte[] valb = (byte[]) regQueryValueEx.invoke(root, new Object[] {new Integer(handles[0]), toCstr(key)});
            regCloseKey.invoke(root, new Object[] {new Integer(handles[0])});
            return (valb != null ? parseValue(valb) : queryValueForKey(hkey, path, key));
        }
    
        private static String queryValueForKey(int hkey, String path, String key) throws IOException {
            return queryValuesForPath(hkey, path).get(key);
        }
    
        private static Map valuesForPath(Preferences root, int hkey, String path)
                throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {
            HashMap results = new HashMap();
            int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {new Integer(hkey), toCstr(path), new Integer(KEY_READ)});
            if (handles[1] != REG_SUCCESS)
                throw new IllegalArgumentException("The system can not find the specified path: '"+getParentKey(hkey)+"\\"+path+"'");
            int[] info = (int[]) regQueryInfoKey.invoke(root, new Object[] {new Integer(handles[0])});
            int count = info[2];                            // Fixed: info[0] was being used here
            int maxlen = info[4];                           // while info[3] was being used here, causing wrong results
            for(int index=0; index valuesForKeyPath(int hkey, String path, String key)
                throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {
            List list = new ArrayList();
            if (hkey == HKEY_LOCAL_MACHINE)
                return valuesForKeyPath(systemRoot, hkey, path, key, list);
            else if (hkey == HKEY_CURRENT_USER)
                return valuesForKeyPath(userRoot, hkey, path, key, list);
            else
                return valuesForKeyPath(null, hkey, path, key, list);
        }
    
        private static List valuesForKeyPath(Preferences root, int hkey, String path, String key, List list)
                throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {
            if(!isDirectory(root, hkey, path)) {
                takeValueInListForKey(hkey, path, key, list);
            } else {
                List subKeys = subKeysForPath(root, hkey, path);
                for(String subkey: subKeys) {
                    String newPath = path+"\\"+subkey;
                    if(isDirectory(root, hkey, newPath))
                        valuesForKeyPath(root, hkey, newPath, key, list);
                    takeValueInListForKey(hkey, newPath, key, list);
                }
            }
            return list;
        }
    
        /**
         * Takes value for key in list
         * @param hkey
         * @param path
         * @param key
         * @param list
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         * @throws IOException
         */
        private static void takeValueInListForKey(int hkey, String path, String key, List list)
                throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {
            String value = valueForKey(hkey, path, key);
            if(value != null)
                list.add(value);
        }
    
        /**
         * Checks if the path has more subkeys or not
         * @param root
         * @param hkey
         * @param path
         * @return true if path has subkeys otherwise false
         * @throws IllegalArgumentException
         * @throws IllegalAccessException
         * @throws InvocationTargetException
         */
        private static boolean isDirectory(Preferences root, int hkey, String path)
                throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
            return !subKeysForPath(root, hkey, path).isEmpty();
        }
    
        private static List subKeysForPath(Preferences root, int hkey, String path)
                throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
            List results = new ArrayList();
            int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {new Integer(hkey), toCstr(path), new Integer(KEY_READ)});
            if (handles[1] != REG_SUCCESS)
                throw new IllegalArgumentException("The system can not find the specified path: '"+getParentKey(hkey)+"\\"+path+"'");
            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 queryValuesForPath(int hkey, String path) throws IOException {
            String line;
            StringBuilder builder = new StringBuilder();
            Map map = new HashMap();
            Process process = Runtime.getRuntime().exec("reg query \""+getParentKey(hkey)+"\\" + path + "\"");
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            while((line = reader.readLine()) != null) {
                if(!line.contains("REG_"))
                    continue;
                StringTokenizer tokenizer = new StringTokenizer(line, " \t");
                while(tokenizer.hasMoreTokens()) {
                    String token = tokenizer.nextToken();
                    if(token.startsWith("REG_"))
                        builder.append("\t ");
                    else
                        builder.append(token).append(" ");
                }
                String[] arr = builder.toString().split("\t");
                map.put(arr[0].trim(), arr[1].trim());
                builder.setLength(0);
            }
            return map;
        }
    
        /**
         * Determines the string equivalent of hkey
         * @param hkey
         * @return string equivalent of hkey
         */
        private static String getParentKey(int hkey) {
            if(hkey == HKEY_CLASSES_ROOT)
                return CLASSES_ROOT;
            else if(hkey == HKEY_CURRENT_USER)
                return CURRENT_USER;
            else if(hkey == HKEY_LOCAL_MACHINE)
                return LOCAL_MACHINE;
            return null;
        }
    
        /**
         *Intern method which adds the trailing \0 for the handle with java.dll
         * @param str String
         * @return byte[] 
         */
        private static byte[] toCstr(String str) {
            if(str == null)
                str = "";
            return (str += "\0").getBytes();
        }
    
        /**
         * Method removes the trailing \0 which is returned from the java.dll (just if the last sign is a \0)
         * @param buf the byte[] buffer which every read method returns
         * @return String a parsed string without the trailing \0
         */
        private static String parseValue(byte buf[]) {
            if(buf == null)
                return null;
            String ret = new String(buf);
            if(ret.charAt(ret.length()-1) == '\0')
                return ret.substring(0, ret.length()-1);
            return ret;
        }
    }  
    

    Sample of using the methods is as follows:

    Below method retrieves the value of the key from the given path:

    String hex = WinRegistry.valueForKey(WinRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update", "AUOptions");
    

    This method retrieves all data for the specified path(in form of keys and values) :

    Map map = WinRegistry.valuesForPath(WinRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WSMAN");
    

    This method retrieves value recursively for the key from the given path:

    String val = WinRegistry.valueForKeyPath(WinRegistry.HKEY_LOCAL_MACHINE, "System", "TypeID");
    

    and this one retrieves all values recursively for a key from the given path:

    List list = WinRegistry.valuesForKeyPath(
                       WinRegistry.HKEY_LOCAL_MACHINE,                  //HKEY                               "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall",   //path                 "DisplayName"         //Key
                );
    

    Here in above code I retrieved all installed software names in windows system.
    Note: See the documentation of these methods

    And this one retrieves all subkeys of the given path:

    List list3 = WinRegistry.subKeysForPath(WinRegistry.HKEY_CURRENT_USER, "Software");
    

    Important Note: I have modified only reading purpose methods in this process, not the writing purpose methods like createKey, deleteKey etc. They still are same as I recieved them.

提交回复
热议问题