如何使用Java讀取/寫入Windows註冊表? java
我增長了David最初發布的Pure java代碼,以容許從64位JVM訪問註冊表的32位部分,反之亦然。 我認爲沒有其餘答案能夠解決這個問題。 windows
這裏是: 數組
/** * 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; } }
另外一個圖書館... app
https://code.google.com/p/java-registry/ ide
這將在後臺啓動reg.exe,以讀取/寫入臨時文件。 我沒有最終使用它,可是它看起來像是一個很是全面的實現。 若是確實使用過它,我可能會深刻研究並添加對子進程的更好管理。 this
我之前對@David的答案的編輯被拒絕了。 這是一些有用的信息。 google
之因此如此有效,是由於Sun將Windows的Preferences
類做爲JDK的一部分來實現,可是它是package私有的 。 實現的一部分使用JNI。 spa
java.util.prefs.WindowsPreferences
私有類: http : //grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/util/prefs/WindowsPreferences.java 在運行時使用工廠方法在此處選擇實現: http : //grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/util/prefs/Preferences.java# Preferences.0factory .net
真正的問題:OpenJDK爲何不公開此API? code
太瘋狂了...我今後處的其中一篇文章中獲取了代碼,卻看不到還有18條註釋,其中有一條說它沒有讀取dword值...
不管如何,我都將代碼的底層重構爲具備更少ifs和method的東西。
枚舉可能有所改進,可是一旦我嘗試讀取數值或字節數組並失敗了,我就放棄了...
因此這裏是:
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<String, String> readStringValues(WinRegistryKey regKey, String key) throws RegistryException { HashMap<String, String> results = new HashMap<String, String>(); 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<String> readStringSubKeys(WinRegistryKey regKey, String key) throws RegistryException { List<String> results = new ArrayList<String>(); 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; } }
注意:這裏不讀任何其餘內容!
您實際上不須要第三者套餐。 Windows具備用於全部註冊表操做的reg實用程序。 要獲取命令格式,請轉到DOS屬性並鍵入:
reg /?
您能夠經過Runtime類調用reg :
Runtime.getRuntime().exec("reg <your parameters here>");
使用上面的命令,編輯密鑰和添加新密鑰很是簡單。 要讀取註冊表,您須要獲取reg的輸出,這有些棘手。 這是代碼:
import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; /** * @author Oleg Ryaboy, based on work by Miguel Enriquez */ public class WindowsReqistry { /** * * @param location path in the registry * @param key registry key * @return registry value or null if not found */ public static final String readRegistry(String location, String key){ try { // Run reg query, then read output with StreamReader (internal class) Process process = Runtime.getRuntime().exec("reg query " + '"'+ location + "\" /v " + key); StreamReader reader = new StreamReader(process.getInputStream()); reader.start(); process.waitFor(); reader.join(); String output = reader.getResult(); // Output has the following format: // \n<Version information>\n\n<key>\t<registry type>\t<value> if( ! output.contains("\t")){ return null; } // Parse out the value String[] parsed = output.split("\t"); return parsed[parsed.length-1]; } catch (Exception e) { return null; } } static class StreamReader extends Thread { private InputStream is; private StringWriter sw= new StringWriter(); public StreamReader(InputStream is) { this.is = is; } public void run() { try { int c; while ((c = is.read()) != -1) sw.write(c); } catch (IOException e) { } } public String getResult() { return sw.toString(); } } public static void main(String[] args) { // Sample usage String value = WindowsReqistry.readRegistry("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\" + "Explorer\\Shell Folders", "Personal"); System.out.println(value); } }