importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;importjava.util.HashMap;importjava.util.Map;importjava.util.ArrayList;importjava.util.List;importjava.util.StringTokenizer;importjava.util.prefs.Preferences;/*** Windows下读取注册表的工具类
*
* 使用这些方法的示例如下:
*
* 下面的方法从给定路径检索键的值:
*
* String hex = WinRegistry.valueForKey(WinRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update", "AUOptions");
*
* 此方法检索指定路径的所有数据(以键和值的形式):
*
* Map map = WinRegistry.valuesForPath(WinRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WSMAN");
*
* 此方法从给定路径递归检索键的值:
*
* String val = WinRegistry.valueForKeyPath(WinRegistry.HKEY_LOCAL_MACHINE, "System", "TypeID");
*
* 并且这个方法递归地从给定路径中检索一个键的所有值:
*
* List list = WinRegistry.valuesForKeyPath( WinRegistry.HKEY_LOCAL_MACHINE, //HKEY "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall", //path "DisplayName" //Key );
*
* 在上面的代码中,我检索了Windows系统中所有已安装的软件名称。
*
* 注意:请参阅这些方法的文档。
*
* 这个检索给定路径的所有子键:
*
* List list3 = WinRegistry.subKeysForPath(WinRegistry.HKEY_CURRENT_USER, "Software");
*
* 注意:在这个过程中,我只修改了阅读目的的方法,而不是像createKey、删除Key等写作目的的方法。它们仍然和我收到的一样。
*
*https://cloud.tencent.com/developer/ask/43600
*/@SuppressWarnings("all")public classWinRegistry {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 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();
}
}/*** Reads value for the key from given path
*@paramhkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
*@parampath
*@paramkey
*@returnthe value
*@throwsIllegalArgumentException
*@throwsIllegalAccessException
*@throwsInvocationTargetException
*@throwsIOException*/
public static String valueForKey(inthkey, String path, String key)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {if (hkey ==HKEY_LOCAL_MACHINE)returnvalueForKey(systemRoot, hkey, path, key);else if (hkey ==HKEY_CURRENT_USER)returnvalueForKey(userRoot, hkey, path, key);else
return valueForKey(null, hkey, path, key);
}/*** Reads all key(s) and value(s) from given path
*@paramhkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
*@parampath
*@returnthe map of key(s) and corresponding value(s)
*@throwsIllegalArgumentException
*@throwsIllegalAccessException
*@throwsInvocationTargetException
*@throwsIOException*/
public static Map valuesForPath(inthkey, String path)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {if (hkey ==HKEY_LOCAL_MACHINE)returnvaluesForPath(systemRoot, hkey, path);else if (hkey ==HKEY_CURRENT_USER)returnvaluesForPath(userRoot, hkey, path);else
return valuesForPath(null, hkey, path);
}/*** Read all the subkey(s) from a given path
*@paramhkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
*@parampath
*@returnthe subkey(s) list
*@throwsIllegalArgumentException
*@throwsIllegalAccessException
*@throwsInvocationTargetException*/
public static List subKeysForPath(inthkey, String path)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException {if (hkey ==HKEY_LOCAL_MACHINE)returnsubKeysForPath(systemRoot, hkey, path);else if (hkey ==HKEY_CURRENT_USER)returnsubKeysForPath(userRoot, hkey, path);else
return subKeysForPath(null, hkey, path);
}/*** Create a key
*@paramhkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
*@paramkey
*@throwsIllegalArgumentException
*@throwsIllegalAccessException
*@throwsInvocationTargetException*/
public static void createKey(inthkey, String key)throwsIllegalArgumentException, 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
*@paramhkey
*@paramkey
*@paramvalueName
*@paramvalue
*@throwsIllegalArgumentException
*@throwsIllegalAccessException
*@throwsInvocationTargetException*/
public static void writeStringValue(inthkey, String key, String valueName, String value)throwsIllegalArgumentException, 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
*@paramhkey
*@paramkey
*@throwsIllegalArgumentException
*@throwsIllegalAccessException
*@throwsInvocationTargetException*/
public static void deleteKey(inthkey, String key)throwsIllegalArgumentException, 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
*@paramhkey
*@paramkey
*@paramvalue
*@throwsIllegalArgumentException
*@throwsIllegalAccessException
*@throwsInvocationTargetException*/
public static void deleteValue(inthkey, String key, String value)throwsIllegalArgumentException, 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, inthkey, String key, String value)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException {int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {new Integer(hkey), toCstr(key), newInteger(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])});returnrc;
}private static int deleteKey(Preferences root, inthkey, String key)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException {int rc =((Integer) regDeleteKey.invoke(root, new Object[] {newInteger(hkey), toCstr(key)})).intValue();return rc; //can REG_NOTFOUND, REG_ACCESSDENIED, REG_SUCCESS
}private static String valueForKey(Preferences root, inthkey, String path, String key)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {new Integer(hkey), toCstr(path), newInteger(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) throwsIOException {returnqueryValuesForPath(hkey, path).get(key);
}private static Map valuesForPath(Preferences root, inthkey, String path)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {
HashMap results = new HashMap();int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {new Integer(hkey), toCstr(path), newInteger(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
String vald=parseValue(valb);if(valb == null ||vald.isEmpty())returnqueryValuesForPath(hkey, path);
results.put(vald, valueForKey(root, hkey, path, vald));
}
regCloseKey.invoke(root,new Object[] {new Integer(handles[0])});returnresults;
}/*** Searches recursively into the path to find the value for key. This method gives
* only first occurrence value of the key. If required to get all values in the path
* recursively for this key, then {@link#valuesForKeyPath(int hkey, String path, String key)}
* should be used.
*@paramhkey
*@parampath
*@paramkey
*@paramlist
*@returnthe value of given key obtained recursively
*@throwsIllegalArgumentException
*@throwsIllegalAccessException
*@throwsInvocationTargetException
*@throwsIOException*/
public static String valueForKeyPath(inthkey, String path, String key)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {
String val;try{
val= valuesForKeyPath(hkey, path, key).get(0);
}catch(IndexOutOfBoundsException e) {throw new IllegalArgumentException("The system can not find the key: '"+key+"' after "
+ "searching the specified path: '"+getParentKey(hkey)+"\\"+path+"'");
}returnval;
}/*** Searches recursively into given path for particular key and stores obtained value in list
*@paramhkey
*@parampath
*@paramkey
*@paramlist
*@returnlist containing values for given key obtained recursively
*@throwsIllegalArgumentException
*@throwsIllegalAccessException
*@throwsInvocationTargetException
*@throwsIOException*/
public static List valuesForKeyPath(inthkey, String path, String key)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {
List list = new ArrayList();if (hkey ==HKEY_LOCAL_MACHINE)returnvaluesForKeyPath(systemRoot, hkey, path, key, list);else if (hkey ==HKEY_CURRENT_USER)returnvaluesForKeyPath(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, Listlist)throwsIllegalArgumentException, 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);
}
}returnlist;
}/*** Takes value for key in list
*@paramhkey
*@parampath
*@paramkey
*@paramlist
*@throwsIllegalArgumentException
*@throwsIllegalAccessException
*@throwsInvocationTargetException
*@throwsIOException*/
private static void takeValueInListForKey(int hkey, String path, String key, Listlist)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException {
String value=valueForKey(hkey, path, key);if(value != null)
list.add(value);
}/*** Checks if the path has more subkeys or not
*@paramroot
*@paramhkey
*@parampath
*@returntrue if path has subkeys otherwise false
*@throwsIllegalArgumentException
*@throwsIllegalAccessException
*@throwsInvocationTargetException*/
private static boolean isDirectory(Preferences root, inthkey, String path)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException {return !subKeysForPath(root, hkey, path).isEmpty();
}private static List subKeysForPath(Preferences root, inthkey, String path)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException {
List results = new ArrayList();int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {new Integer(hkey), toCstr(path), newInteger(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
results.add(parseValue(valb));
}
regCloseKey.invoke(root,new Object[] {new Integer(handles[0])});returnresults;
}private static int [] createKey(Preferences root, inthkey, String key)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException {return (int[]) regCreateKeyEx.invoke(root, new Object[] {newInteger(hkey), toCstr(key)});
}private static void writeStringValue(Preferences root, inthkey, String key, String valueName, String value)throwsIllegalArgumentException, IllegalAccessException, InvocationTargetException {int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {new Integer(hkey), toCstr(key), newInteger(KEY_ALL_ACCESS)});
regSetValueEx.invoke(root,new Object[] {new Integer(handles[0]), toCstr(valueName), toCstr(value)});
regCloseKey.invoke(root,new Object[] {new Integer(handles[0])});
}/*** Makes cmd query for the given hkey and path then executes the query
*@paramhkey
*@parampath
*@returnthe map containing all results in form of key(s) and value(s) obtained by executing query
*@throwsIOException*/
private static Map queryValuesForPath(int hkey, String path) throwsIOException {
String line;
StringBuilder builder= newStringBuilder();
Map map = new HashMap();
Process process= Runtime.getRuntime().exec("reg query \""+getParentKey(hkey)+"\\" + path + "\"");
BufferedReader reader= new BufferedReader(newInputStreamReader(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 ");elsebuilder.append(token).append(" ");
}
String[] arr= builder.toString().split("\t");
map.put(arr[0].trim(), arr[1].trim());
builder.setLength(0);
}returnmap;
}/*** Determines the string equivalent of hkey
*@paramhkey
*@returnstring equivalent of hkey*/
private static String getParentKey(inthkey) {if(hkey ==HKEY_CLASSES_ROOT)returnCLASSES_ROOT;else if(hkey ==HKEY_CURRENT_USER)returnCURRENT_USER;else if(hkey ==HKEY_LOCAL_MACHINE)returnLOCAL_MACHINE;return null;
}/***Intern method which adds the trailing \0 for the handle with java.dll
*@paramstr String
*@returnbyte[]*/
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)
*@parambuf the byte[] buffer which every read method returns
*@returnString a parsed string without the trailing \0*/
private static String parseValue(bytebuf[]) {if(buf == null)return null;
String ret= newString(buf);if(ret.charAt(ret.length()-1) == '\0')return ret.substring(0, ret.length()-1);returnret;
}
}