Read/write to Windows registry using Java

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

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

24条回答
  •  攒了一身酷
    2020-11-21 06:17

    This was crazy... I took the code from one of the posts here, failed to see there were 18 more comments in which one stated that it does not read a dword value...

    In any case, I've refactored the hell of that code into something with less ifs and methods...

    The Enum could be refined a bit, but as soon as I've fought my way to read a numeric value or byte array and failed, I've given up...

    So here it is:

    package com.nu.art.software.utils;
    
    
    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;
    
    /**
     *
     * @author TacB0sS
     */
    public class WinRegistry_TacB0sS {
    
        public static final class RegistryException
                extends Exception {
    
            private static final long serialVersionUID = -8799947496460994651L;
    
            public RegistryException(String message, Throwable e) {
                super(message, e);
            }
    
            public RegistryException(String message) {
                super(message);
            }
    
    
        }
    
        public static final int KEY_WOW64_32KEY = 0x0200;
    
        public static final int KEY_WOW64_64KEY = 0x0100;
    
        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;
    
        public enum WinRegistryKey {
            User(Preferences.userRoot(), 0x80000001), ;
    
            // System(Preferences.systemRoot(), 0x80000002);
    
            private final Preferences preferencesRoot;
    
            private final Integer key;
    
            private WinRegistryKey(Preferences preferencesRoot, int key) {
                this.preferencesRoot = preferencesRoot;
                this.key = key;
            }
        }
    
        private enum WinRegistryMethod {
            OpenKey("WindowsRegOpenKey", int.class, byte[].class, int.class) {
    
                @Override
                protected void verifyReturnValue(Object retValue)
                        throws RegistryException {
                    int[] retVal = (int[]) retValue;
                    if (retVal[1] != REG_SUCCESS)
                        throw new RegistryException("Action Failed, Return Code: " + retVal[1]);
                }
            },
            CreateKeyEx("WindowsRegCreateKeyEx", int.class, byte[].class) {
    
                @Override
                protected void verifyReturnValue(Object retValue)
                        throws RegistryException {
                    int[] retVal = (int[]) retValue;
                    if (retVal[1] != REG_SUCCESS)
                        throw new RegistryException("Action Failed, Return Code: " + retVal[1]);
                }
            },
            DeleteKey("WindowsRegDeleteKey", int.class, byte[].class) {
    
                @Override
                protected void verifyReturnValue(Object retValue)
                        throws RegistryException {
                    int retVal = ((Integer) retValue).intValue();
                    if (retVal != REG_SUCCESS)
                        throw new RegistryException("Action Failed, Return Code: " + retVal);
                }
            },
            DeleteValue("WindowsRegDeleteValue", int.class, byte[].class) {
    
                @Override
                protected void verifyReturnValue(Object retValue)
                        throws RegistryException {
                    int retVal = ((Integer) retValue).intValue();
                    if (retVal != REG_SUCCESS)
                        throw new RegistryException("Action Failed, Return Code: " + retVal);
                }
            },
            CloseKey("WindowsRegCloseKey", int.class),
            QueryValueEx("WindowsRegQueryValueEx", int.class, byte[].class),
            EnumKeyEx("WindowsRegEnumKeyEx", int.class, int.class, int.class),
            EnumValue("WindowsRegEnumValue", int.class, int.class, int.class),
            QueryInfoKey("WindowsRegQueryInfoKey", int.class),
            SetValueEx("WindowsRegSetValueEx", int.class, byte[].class, byte[].class);
    
            private Method method;
    
            private WinRegistryMethod(String methodName, Class... classes) {
                // WinRegistryKey.User.preferencesRoot.getClass().getMDeclaredMethods()
                try {
                    method = WinRegistryKey.User.preferencesRoot.getClass().getDeclaredMethod(methodName, classes);
                } catch (Exception e) {
                    System.err.println("Error");
                    System.err.println(e);
                }
                method.setAccessible(true);
            }
    
            public Object invoke(Preferences root, Object... objects)
                    throws RegistryException {
                Object retValue;
                try {
                    retValue = method.invoke(root, objects);
                    verifyReturnValue(retValue);
                } catch (Throwable e) {
                    String params = "";
                    if (objects.length > 0) {
                        params = objects[0].toString();
                        for (int i = 1; i < objects.length; i++) {
                            params += ", " + objects[i];
                        }
                    }
                    throw new RegistryException("Error invoking method: " + method + ", with params: (" + params + ")", e);
                }
                return retValue;
            }
    
            protected void verifyReturnValue(Object retValue)
                    throws RegistryException {}
        }
    
        private WinRegistry_TacB0sS() {}
    
        public static String readString(WinRegistryKey regKey, String key, String valueName)
                throws RegistryException {
            int retVal = ((int[]) WinRegistryMethod.OpenKey.invoke(regKey.preferencesRoot, regKey.key, toCstr(key),
                    new Integer(KEY_READ)))[0];
    
            byte[] retValue = (byte[]) WinRegistryMethod.QueryValueEx.invoke(regKey.preferencesRoot, retVal,
                    toCstr(valueName));
            WinRegistryMethod.CloseKey.invoke(regKey.preferencesRoot, retVal);
    
            /*
             * Should this return an Empty String.
             */
            return (retValue != null ? new String(retValue).trim() : null);
        }
    
        public static Map readStringValues(WinRegistryKey regKey, String key)
                throws RegistryException {
            HashMap results = new HashMap();
            int retVal = ((int[]) WinRegistryMethod.OpenKey.invoke(regKey.preferencesRoot, regKey.key, toCstr(key),
                    new Integer(KEY_READ)))[0];
    
            int[] info = (int[]) WinRegistryMethod.QueryInfoKey.invoke(regKey.preferencesRoot, retVal);
    
            int count = info[2]; // count
            int maxlen = info[3]; // value length max
            for (int index = 0; index < count; index++) {
                byte[] name = (byte[]) WinRegistryMethod.EnumValue.invoke(regKey.preferencesRoot, retVal,
                        new Integer(index), new Integer(maxlen + 1));
                String value = readString(regKey, key, new String(name));
                results.put(new String(name).trim(), value);
            }
    
            WinRegistryMethod.CloseKey.invoke(regKey.preferencesRoot, retVal);
            return results;
        }
    
        public static List readStringSubKeys(WinRegistryKey regKey, String key)
                throws RegistryException {
            List results = new ArrayList();
            int retVal = ((int[]) WinRegistryMethod.OpenKey.invoke(regKey.preferencesRoot, regKey.key, toCstr(key),
                    new Integer(KEY_READ)))[0];
    
            int[] info = (int[]) WinRegistryMethod.QueryInfoKey.invoke(regKey.preferencesRoot, retVal);
    
            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[]) WinRegistryMethod.EnumValue.invoke(regKey.preferencesRoot, retVal,
                        new Integer(index), new Integer(maxlen + 1));
                results.add(new String(name).trim());
            }
    
            WinRegistryMethod.CloseKey.invoke(regKey.preferencesRoot, retVal);
            return results;
        }
    
        public static void createKey(WinRegistryKey regKey, String key)
                throws RegistryException {
            int[] retVal = (int[]) WinRegistryMethod.CreateKeyEx.invoke(regKey.preferencesRoot, regKey.key, toCstr(key));
            WinRegistryMethod.CloseKey.invoke(regKey.preferencesRoot, retVal[0]);
        }
    
        public static void writeStringValue(WinRegistryKey regKey, String key, String valueName, String value)
                throws RegistryException {
            int retVal = ((int[]) WinRegistryMethod.OpenKey.invoke(regKey.preferencesRoot, regKey.key, toCstr(key),
                    new Integer(KEY_ALL_ACCESS)))[0];
    
            WinRegistryMethod.SetValueEx.invoke(regKey.preferencesRoot, retVal, toCstr(valueName), toCstr(value));
            WinRegistryMethod.CloseKey.invoke(regKey.preferencesRoot, retVal);
        }
    
        public static void deleteKey(WinRegistryKey regKey, String key)
                throws RegistryException {
            WinRegistryMethod.DeleteKey.invoke(regKey.preferencesRoot, regKey.key, toCstr(key));
        }
    
        public static void deleteValue(WinRegistryKey regKey, String key, String value)
                throws RegistryException {
            int retVal = ((int[]) WinRegistryMethod.OpenKey.invoke(regKey.preferencesRoot, regKey.key, toCstr(key),
                    new Integer(KEY_ALL_ACCESS)))[0];
            WinRegistryMethod.DeleteValue.invoke(regKey.preferencesRoot, retVal, toCstr(value));
            WinRegistryMethod.CloseKey.invoke(regKey.preferencesRoot, retVal);
        }
    
        // 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;
        }
    }
    

    NOTE: THIS DOES NOT READ ANYTHING ELSE BUT STRINGS!!!!!

提交回复
热议问题