使用 Java 读取/写入 Windows 注册表
Posted
技术标签:
【中文标题】使用 Java 读取/写入 Windows 注册表【英文标题】:Read/write to Windows registry using Java 【发布时间】:2010-09-08 21:41:22 【问题描述】:如何?
【问题讨论】:
我想说最简单的方法是使用com.sun.deploy.association.utility.WinRegistryWrapper
@Jire 这在各方面都比公认的解决方案要好,只是您需要将 java 安装中的“deploy.jar”包含在项目中——它不会自动包含在内。它也遇到了同样的大问题——除了字符串(甚至多字符串)之外,它不能处理任何东西。您可以使用一些示例将其添加为新答案。如果您没有足够高的代表来发布此问题,请告诉我,我会为您完成。
【参考方案1】:
我知道这个问题很老,但它是谷歌上“java 读/写注册表”的第一个搜索结果。最近我发现了这段惊人的代码:
可以读/写注册表的任何部分。 不使用 JNI。 不使用任何第 3 方/外部应用程序来工作。 不使用 WINDOWS API(直接)这是纯 Java 代码。
它使用反射来工作,通过实际访问java.util.prefs.Preferences
类中的私有方法。这个类的内部比较复杂,但是这个类本身非常好用。
例如,以下代码从注册表获取确切的 windows 分布:
String value = WinRegistry.readString (
WinRegistry.HKEY_LOCAL_MACHINE, //HKEY
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", //Key
"ProductName"); //ValueName
System.out.println("Windows Distribution = " + value);
这是原来的类。只需复制粘贴它,它应该可以工作:
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;
private static final int KEY_ALL_ACCESS = 0xf003f;
private static final int KEY_READ = 0x20019;
private static final Preferences userRoot = Preferences.userRoot();
private static final Preferences systemRoot = Preferences.systemRoot();
private static final Class<? extends Preferences> userClass = userRoot.getClass();
private static final Method regOpenKey;
private static final Method regCloseKey;
private static final Method regQueryValueEx;
private static final Method regEnumValue;
private static final Method regQueryInfoKey;
private static final Method regEnumKeyEx;
private static final Method regCreateKeyEx;
private static final Method regSetValueEx;
private static final Method regDeleteKey;
private static final Method regDeleteValue;
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)
throw new RuntimeException(e);
private WinRegistry()
/**
* 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
if (hkey == HKEY_LOCAL_MACHINE)
return readString(systemRoot, hkey, key, valueName);
else if (hkey == HKEY_CURRENT_USER)
return readString(userRoot, hkey, key, valueName);
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
* @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
if (hkey == HKEY_LOCAL_MACHINE)
return readStringValues(systemRoot, hkey, key);
else if (hkey == HKEY_CURRENT_USER)
return readStringValues(userRoot, hkey, key);
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
* @return the value name(s)
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static List<String> readStringSubKeys(int hkey, String key)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
if (hkey == HKEY_LOCAL_MACHINE)
return readStringSubKeys(systemRoot, hkey, key);
else if (hkey == HKEY_CURRENT_USER)
return readStringSubKeys(userRoot, hkey, key);
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
* @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 readString(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_READ) );
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)
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) );
if (handles[1] != REG_SUCCESS)
return null;
int[] info = (int[]) regQueryInfoKey.invoke(root,
new Object[] new Integer(handles[0]) );
int count = info[0]; // 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));
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)
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)
);
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)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
int[] handles = (int[]) regOpenKey.invoke(root, new Object[]
new Integer(hkey), toCstr(key), new Integer(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]) );
// 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;
原作者:阿帕奇。
库来源:https://github.com/apache/npanday/tree/trunk/components/dotnet-registry/src/main/java/npanday/registry
【讨论】:
这段代码有一个小错误; readStringSubKeys 枚举注册表项的子项不起作用。将私有 readStringSubKeys 函数中的“int count = info[2]; // count ”替换为“int count = info[0]; // count”,这样就可以解决问题。正确的值可以在反映的 WindowsPreferences.SUBKEYS_NUMBER 字段中看到。 我如何让它读取一个双字?他的示例适用于字符串,但我现在需要获取一个实际值才能读取。只是作为 null 出来。 这是在 Apache 许可下获得许可的,给出了一些 google searching。 这很讨厌 - 它涉及通过反射调用非公共方法。换句话说,您超出了 Javadocs 中描述的 Preferences 合同,并且此代码可能会在 Oracle 推出新更新时中断。 此代码可能不再适用于Java 9
,因为它会生成以下警告:An illegal reflective access operation has occurred
【参考方案2】:
您实际上并不需要 3rd 方包。 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);
【讨论】:
Oleg,这真的很有用,谢谢!请注意,如果要读取 process.getErrorStream() 的输出,readRegistry 方法可以添加第二个 StreamReader。附言“new StringWriter();;”中有一个额外的分号。 这段代码很好用!但是,您的解析存在问题。在我的 Windows 7 设置中,没有制表符。解析代码应该更健壮一些。我在我的实现中对其进行了更改,以寻找确保它具有输出的密钥。然后我使用正则表达式在空格上拆分并获取最后一个字符串。这应该始终是键的值。 谁能解释一下为什么这里的阅读是多线程的? 这很好用,除非键中有空格。为了防止它应该是 Process process = Runtime.getRuntime().exec("reg query " + '"'+ location + "\" /v \"" + key + "\""); 在回答我自己的评论时,问题与此有关 (***.com/questions/252297/…)。基本上 reg.exe 是 64 位的,而 JVM 可能是 32 位的,所以他们可以在不同的地方寻找密钥。解决方法是使用两条路径调用两次【参考方案3】:Java Native Access (JNA) 是一个使用原生库的优秀项目,通过Advapi32Util 和Advapi32 支持平台库 (platform.jar) 中的 Windows 注册表。
更新:这是一个 sn-p,其中包含一些示例,说明使用 JNA 3.4.1 与 Windows 注册表一起使用是多么容易,
import com.sun.jna.platform.win32.Advapi32Util;
import com.sun.jna.platform.win32.WinReg;
public class WindowsRegistrySnippet
public static void main(String[] args)
// Read a string
String productName = Advapi32Util.registryGetStringValue(
WinReg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductName");
System.out.printf("Product Name: %s\n", productName);
// Read an int (& 0xFFFFFFFFL for large unsigned int)
int timeout = Advapi32Util.registryGetIntValue(
WinReg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows", "ShutdownWarningDialogTimeout");
System.out.printf("Shutdown Warning Dialog Timeout: %d (%d as unsigned long)\n", timeout, timeout & 0xFFFFFFFFL);
// Create a key and write a string
Advapi32Util.registryCreateKey(WinReg.HKEY_CURRENT_USER, "SOFTWARE\\***");
Advapi32Util.registrySetStringValue(WinReg.HKEY_CURRENT_USER, "SOFTWARE\\***", "url", "http://***.com/a/6287763/277307");
// Delete a key
Advapi32Util.registryDeleteKey(WinReg.HKEY_CURRENT_USER, "SOFTWARE\\***");
【讨论】:
这是 LGPL,这可能是一个问题,包括它在商业软件中。 @kevinarpe “商业许可安排可协商”。没有固定价格对我来说是一个危险信号。 根据我的经验,LGPL 许可软件可以与商业软件一起重新分发(GPL 的限制性更强)。当然,您应该始终咨询您的法律部门(并且可能已经咨询过)。看起来 JNA 将获得双重许可,以便在 JNA 4.0 发布时允许在 Apache 2.0 下重新分发(请参阅github.com/twall/jna/blob/master/LICENSE)。 JNA 4.0+ 现在获得 Apache 2 许可 (see here)。一个非 hacky 解决方案的大 +1。 @ChetanBhagat 我不明白你在做什么。这是关于使用Windows Registry,这是非常特定于 Windows 操作系统的。没有等同于 linux 上的注册表。见Linux equivalent of Windows Registry【参考方案4】:我增加了最初由 David 发布的 Pure java 代码,以允许从 64 位 JVM 访问注册表的 32 位部分,反之亦然。我认为其他任何答案都无法解决这个问题。
这里是:
/**
* Pure Java Windows Registry access.
* Modified by petrucio@***(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;
【讨论】:
干得好。如果您想在 64 位 JRE 中访问 32 位注册表,此解决方案会有所帮助,反之亦然 所以一旦我在路径中给出,readString基本上会读取相应的值?就像在调用此方法时我应该将 hkey 插入我希望读取的位置正确? @Petrucio 此代码不适用于 Linux(CentOS7) 环境。请给我任何其他解决方案。 @ChetanBhagat 对不起,伙计,我有一段时间没有开发 Java,更不用说在 Linux 中开发了。你必须找到自己的解决方案。 在 Java11(可能更早)下,某些类型必须从int
更改为 long
才能再次工作。【参考方案5】:
我在使用jRegistryKey 之前已经这样做了。它是一个 LGPL Java/JNI 库,可以满足您的需求。这是我如何使用它通过 regedit 启用注册表编辑的示例,以及通过注册表在 Windows 中为我自己启用“显示文件夹选项”选项。
import java.io.File;
import ca.beq.util.win32.registry.RegistryKey;
import ca.beq.util.win32.registry.RegistryValue;
import ca.beq.util.win32.registry.RootKey;
import ca.beq.util.win32.registry.ValueType;
public class FixStuff
private static final String REGEDIT_KEY = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
private static final String REGEDIT_VALUE = "DisableRegistryTools";
private static final String REGISTRY_LIBRARY_PATH = "\\lib\\jRegistryKey.dll";
private static final String FOLDER_OPTIONS_KEY = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer";
private static final String FOLDER_OPTIONS_VALUE = "NoFolderOptions";
public static void main(String[] args)
//Load JNI library
RegistryKey.initialize( new File(".").getAbsolutePath()+REGISTRY_LIBRARY_PATH );
enableRegistryEditing(true);
enableShowFolderOptions(true);
private static void enableShowFolderOptions(boolean enable)
RegistryKey key = new RegistryKey(RootKey.HKEY_CURRENT_USER,FOLDER_OPTIONS_KEY);
RegistryKey key2 = new RegistryKey(RootKey.HKEY_LOCAL_MACHINE,FOLDER_OPTIONS_KEY);
RegistryValue value = new RegistryValue();
value.setName(FOLDER_OPTIONS_VALUE);
value.setType(ValueType.REG_DWORD_LITTLE_ENDIAN);
value.setData(enable?0:1);
if(key.hasValue(FOLDER_OPTIONS_VALUE))
key.setValue(value);
if(key2.hasValue(FOLDER_OPTIONS_VALUE))
key2.setValue(value);
private static void enableRegistryEditing(boolean enable)
RegistryKey key = new RegistryKey(RootKey.HKEY_CURRENT_USER,REGEDIT_KEY);
RegistryValue value = new RegistryValue();
value.setName(REGEDIT_VALUE);
value.setType(ValueType.REG_DWORD_LITTLE_ENDIAN);
value.setData(enable?0:1);
if(key.hasValue(REGEDIT_VALUE))
key.setValue(value);
【讨论】:
这不支持64位!编写它的人需要您的帮助来添加 64 位 JVM 支持。 sourceforge.net/tracker/… 它在 Maven Central 上也不可用。【参考方案6】:是的,使用 java.util.Preferences API,因为它的 Windows 实现使用注册表作为后端。
最终,这取决于您想要做什么:为您的应用存储首选项是 Preferences 所做的非常棒的事情。如果您想实际更改与您的应用程序无关的注册表项,您将需要一些 JNI 应用程序,如 Mark 所述(此处无耻窃取):
来自快速谷歌: 检查 JNIWrapper 的 WinPack。它具有完整的 Windows 注册表访问支持,包括读取和写入。
WinPack Demo 以注册表查看器为例。
查看http://www.teamdev.com/jniwrapper/winpack/#registry_access
还有……
还有试试JNIRegistry@http://www.trustice.com/java/jnireg/
还有调用外部应用程序的选项,它负责读/写注册表。
【讨论】:
那么,如何使用 Preferences API 编辑 HKEY_CLASSES_ROOT? 为此,您需要一个 JNI 应用程序【参考方案7】:来自快速谷歌:
检查 JNIWrapper 的 WinPack。它 拥有完整的 Windows 注册表访问权限 支持包括阅读和写作。
WinPack Demo 有注册表查看器 作为示例实现。
查看 http://www.teamdev.com/jniwrapper/winpack/#registry_access
还有……
还有试试 JNIRegistry @ http://www.trustice.com/java/jnireg/
还有调用外部应用程序的选项,它负责读/写注册表。
【讨论】:
【参考方案8】:这是 Oleg 解决方案的修改版本。我注意到在我的系统(Windows server 2003)上,“reg query”的输出不是由制表符('\t')分隔,而是由 4 个空格分隔。
我还简化了解决方案,因为不需要线程。
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);
InputStream is = process.getInputStream();
StringBuilder sw = new StringBuilder();
try
int c;
while ((c = is.read()) != -1)
sw.append((char)c);
catch (IOException e)
String output = sw.toString();
// Output has the following format:
// \n<Version information>\n\n<key> <registry type> <value>\r\n\r\n
int i = output.indexOf("REG_SZ");
if (i == -1)
return null;
sw = new StringBuilder();
i += 6; // skip REG_SZ
// skip spaces or tabs
for (;;)
if (i > output.length())
break;
char c = output.charAt(i);
if (c != ' ' && c != '\t')
break;
++i;
// take everything until end of line
for (;;)
if (i > output.length())
break;
char c = output.charAt(i);
if (c == '\r' || c == '\n')
break;
sw.append(c);
++i;
return sw.toString();
catch (Exception e)
return null;
【讨论】:
尽管这已经快 10 年了,但它仍然是谷歌搜索结果中的佼佼者,所以给未来用户的建议:进行两个 reg 查询,一个使用“/reg:32”,一个使用"/reg:64" 以确保它正常工作。例如,Steam 对我来说是 64 位的。除非我添加 /reg:32,否则查询 HKLM\SOFTWARE\Valve\Steam\InstallPath 会失败,因为“真实”键是 HKLM\SOFTWARE\WOW6432Node\Valve.. 更正:steam 是 32 位的,我的操作系统是 64 位的。抱歉,编辑太晚了【参考方案9】:感谢原帖。我已经重新设计了这个实用程序类,并提出了它之前的缺陷,认为它可能会帮助其他人,所以在这里发布。我还添加了一些额外的实用方法。现在它可以读取 Windows 注册表中的任何文件(包括 REG_DWORD、REG_BINARY、REG_EXPAND_SZ 等)。所有方法都像魅力一样起作用。只需复制并粘贴它,它应该可以工作。这是重新设计和修改的类:
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<? 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
* @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<String, String> 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<String> 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<String,String> valuesForPath(Preferences root, int hkey, String path)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException
HashMap<String, String> results = new HashMap<String,String>();
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<count; index++)
byte[] valb = (byte[]) regEnumValue.invoke(root, new Object[] new Integer(handles[0]), new Integer(index), new Integer(maxlen + 1));
String vald = parseValue(valb);
if(valb == null || vald.isEmpty())
return queryValuesForPath(hkey, path);
results.put(vald, valueForKey(root, hkey, path, vald));
regCloseKey.invoke(root, new Object[] new Integer(handles[0]));
return results;
/**
* 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.
* @param hkey
* @param path
* @param key
* @param list
* @return the value of given key obtained recursively
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws IOException
*/
public static String valueForKeyPath(int hkey, String path, String key)
throws IllegalArgumentException, 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+"'");
return val;
/**
* Searches recursively into given path for particular key and stores obtained value in list
* @param hkey
* @param path
* @param key
* @param list
* @return list containing values for given key obtained recursively
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws IOException
*/
public static List<String> valuesForKeyPath(int hkey, String path, String key)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException
List<String> list = new ArrayList<String>();
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<String> valuesForKeyPath(Preferences root, int hkey, String path, String key, List<String> list)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, IOException
if(!isDirectory(root, hkey, path))
takeValueInListForKey(hkey, path, key, list);
else
List<String> 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<String> 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<String> subKeysForPath(Preferences root, int hkey, String path)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
List<String> results = new ArrayList<String>();
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<count; index++)
byte[] valb = (byte[]) regEnumKeyEx.invoke(root, new Object[] new Integer(handles[0]), new Integer(index), new Integer(maxlen + 1));
results.add(parseValue(valb));
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)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
int[] handles = (int[]) regOpenKey.invoke(root, new Object[] new Integer(hkey), toCstr(key), new Integer(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
* @param hkey
* @param path
* @return the map containing all results in form of key(s) and value(s) obtained by executing query
* @throws IOException
*/
private static Map<String, String> queryValuesForPath(int hkey, String path) throws IOException
String line;
StringBuilder builder = new StringBuilder();
Map<String, String> map = new HashMap<String, String>();
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;
使用方法示例如下:
以下方法从给定路径中检索键的值:
String hex = WinRegistry.valueForKey(WinRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update", "AUOptions");
此方法检索指定路径的所有数据(以键和值的形式):
Map<String, String> map = WinRegistry.valuesForPath(WinRegistry.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WSMAN");
此方法从给定路径递归检索键的值:
String val = WinRegistry.valueForKeyPath(WinRegistry.HKEY_LOCAL_MACHINE, "System", "TypeID");
这个从给定路径递归地检索一个键的所有值:
List<String> list = WinRegistry.valuesForKeyPath(
WinRegistry.HKEY_LOCAL_MACHINE, //HKEY "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall", //path "DisplayName" //Key
);
在上面的代码中,我在 windows 系统中检索了所有已安装的软件名称。注意:请参阅这些方法的文档
这个检索给定路径的所有子键:
List<String> list3 = WinRegistry.subKeysForPath(WinRegistry.HKEY_CURRENT_USER, "Software");
重要提示:我在这个过程中只修改了读取目的方法,而不是createKey,deleteKey等写入目的方法。它们仍然和我收到的一样。
【讨论】:
当我将注册表写入 HKEY_LOCAL_MACHINE 时,错误显示为 java.lang.IllegalArgumentException: rc=5 key=SOFTWARE\rgagnon.com\aa。 WinRegistry.createKey(WinRegistry.java:157)。如何解决。 请阅读最后的重要说明,我没有修改写注册表目的方法,它们与收到的相同。 对这个解决方案要非常小心,它与接受的答案不同。在最底层,它将对 Preference 类的调用替换为对“reg query”命令的调用,但它看起来很像已接受的答案,您可能不会马上意识到这一点。【参考方案10】:写入寄存器的最佳方式可能是使用 reg import
原生 Windows 命令,并为其提供通过从注册表导出某些内容而生成的 .reg
文件的文件路径。
使用reg query
命令完成读取。另请参阅文档:
https://technet.microsoft.com/en-us/library/cc742028.aspx
因此下面的代码应该是不言自明的:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
public class WindowsRegistry
public static void importSilently(String regFilePath) throws IOException,
InterruptedException
if (!new File(regFilePath).exists())
throw new FileNotFoundException();
Process importer = Runtime.getRuntime().exec("reg import " + regFilePath);
importer.waitFor();
public static void overwriteValue(String keyPath, String keyName,
String keyValue) throws IOException, InterruptedException
Process overwriter = Runtime.getRuntime().exec(
"reg add " + keyPath + " /t REG_SZ /v \"" + keyName + "\" /d "
+ keyValue + " /f");
overwriter.waitFor();
public static String getValue(String keyPath, String keyName)
throws IOException, InterruptedException
Process keyReader = Runtime.getRuntime().exec(
"reg query \"" + keyPath + "\" /v \"" + keyName + "\"");
BufferedReader outputReader;
String readLine;
StringBuffer outputBuffer = new StringBuffer();
outputReader = new BufferedReader(new InputStreamReader(
keyReader.getInputStream()));
while ((readLine = outputReader.readLine()) != null)
outputBuffer.append(readLine);
String[] outputComponents = outputBuffer.toString().split(" ");
keyReader.waitFor();
return outputComponents[outputComponents.length - 1];
【讨论】:
【参考方案11】:如前所述,Preferences API 使用注册表来存储首选项,但不能用于访问整个注册表。
然而,一位名叫 David Croft 的海盗发现,可以在 Sun 的 reading the Windows registry from Java without JNI 的 Preferences API 实现中使用方法。这样做有一些危险,但值得一看。
【讨论】:
【参考方案12】:很少有 JNDI 服务提供者可以使用 Windows 注册表。
可以观察http://java.sun.com/products/jndi/serviceproviders.html。
【讨论】:
【参考方案13】:Preferences API 方法无法让您访问注册表的所有分支。事实上,它只允许您访问 Preferences API 存储其偏好的位置。它不是像 .NET 那样的通用注册表处理 API
如 Mark 所示,我猜想 JNI 或外部工具可以读取/写入每个键。
【讨论】:
我讨厌 Preferences API 实际上是 Java 本身的偏好。我希望它像你说的那样更通用。【参考方案14】:你可以试试WinRun4J。这是一个 windows java 启动器和服务主机,但它也提供了一个用于访问注册表的库。
(顺便说一句,我在这个项目上工作,所以如果您有任何问题,请告诉我)
【讨论】:
【参考方案15】:我之前对@David 的回答的编辑被拒绝了。这里有一些关于它的有用信息。
这种“魔法”之所以有效,是因为 Sun 为 Windows 实现了 Preferences
类作为 JDK 的一部分,但它是 package private。部分实现使用 JNI。
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
在运行时使用工厂方法选择实现:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/util/prefs/Preferences.java#Preferences.0factory
真正的问题:为什么 OpenJDK 不向公众公开这个 API?
【讨论】:
所有 JDK 函数都应该可以在任何操作系统上运行,因此它们不会公开 WindowsPreferences,而只是公开 Preferences,其中包含应该在任何地方都可以运行的函数。【参考方案16】:java.util.prefs
包为应用程序提供了一种存储和检索用户和系统首选项以及数据配置的方法。这些偏好数据将永久存储在依赖于实现的支持存储中。例如在 Windows 操作系统中将存储在 Windows 注册表中。
要写入和读取这些数据,我们使用java.util.prefs.Preferences
类。下面的代码展示了如何读写注册表中的HKCU
和HKLM
。
import java.util.prefs.Preferences;
public class RegistryDemo
public static final String PREF_KEY = "org.username";
public static void main(String[] args)
//
// Write Preferences information to HKCU (HKEY_CURRENT_USER),
// HKCU\Software\JavaSoft\Prefs\org.username
//
Preferences userPref = Preferences.userRoot();
userPref.put(PREF_KEY, "xyz");
//
// Below we read back the value we've written in the code above.
//
System.out.println("Preferences = "
+ userPref.get(PREF_KEY, PREF_KEY + " was not found."));
//
// Write Preferences information to HKLM (HKEY_LOCAL_MACHINE),
// HKLM\Software\JavaSoft\Prefs\org.username
//
Preferences systemPref = Preferences.systemRoot();
systemPref.put(PREF_KEY, "xyz");
//
// Read back the value we've written in the code above.
//
System.out.println("Preferences = "
+ systemPref.get(PREF_KEY, PREF_KEY + " was not found."));
【讨论】:
【参考方案17】:又一个库...
https://code.google.com/p/java-registry/
这个会在后台启动 reg.exe,读取/写入临时文件。我最终没有使用它,但它看起来是一个非常全面的实现。如果我确实使用了它,我可能会深入研究并添加对子进程的更好管理。
【讨论】:
不提供原生实现,只是经常调用 regedit.exe。 工作得很好。 @AlexByrth 可能适合您,但 (1) 不适用于无法在本地写入文件的软件,这确实会发生,(2) 一旦 reg.exe 更改输入就会失败或输出格式,(3) 当您为企业客户编写代码时,出于某种安全原因,禁用调用 reg.exe 或根本调用任何程序(是的,这些确实存在)时,将失败。此外,在 Windows 上调用外部程序很慢。 @toolforger,好点,但建议的解决方案解决了我的问题。您描述的情况也是其他几个选择的死胡同。除了可能以管理员身份运行的全功能安装程序包外,没有简单的通用解决方案。用来杀死蚂蚁的火箭筒。 @AlexByrth “为我工作”适用于“需要为除我以外的任何人工作”的情况。大多数代码必须为其他代码工作,然后像那些基于外部程序的解决方案,这些程序使用未记录的输出格式,可能会随着每个 Windows 版本而改变,根本行不通。基于 JNA 的解决方案适用于记录在案的 MS API - 这并不意味着它永远不会改变,但至少您会收到警告,并且 JNA 库可能会及时更新,因此您甚至不会注意到某些内容改变了。【参考方案18】:虽然这已经很老了,但我想在 Windows 平台上使用更好的实用程序是regini
:
对进程的一次调用:
Runtime.getRuntime().exec("regini <your script file abs path here>");
会做所有的魔法。我已经尝试过了,同时使用 servany.exe 将 jar 作为 Windows 服务,这需要在注册表中进行更改以添加 javaw.exe 参数,并且效果很好。您可能想阅读以下内容:http://support.microsoft.com/kb/264584
【讨论】:
【参考方案19】:这太疯狂了...我从这里的一篇帖子中获取了代码,没有看到还有 18 个 cmets,其中一个说它没有读取 dword 值...
无论如何,我已经将那段地狱般的代码重构为更少的 if 和方法......
枚举可以稍微改进一下,但是一旦我努力读取数值或字节数组并且失败了,我就放弃了......
原来是这样:
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;
注意:除了字符串之外,这不会读取任何其他内容!!!!!!
【讨论】:
【参考方案20】:WinPack Demo 有注册表查看器 作为示例实现。
查看 http://www.jniwrapper.com/winpack_features.jsp#registry
顺便说一句,WinPack 已移至以下地址:
http://www.teamdev.com/jniwrapper/winpack/
【讨论】:
【参考方案21】:它使用与in David's answer 相同的Java 内部API,但我已经完全重写了它。它现在更短,更好用。我还添加了对 HKEY_CLASSES_ROOT 和其他配置单元的支持。但是它仍然有一些其他的限制(例如不支持 DWORD 和不支持 Unicode),这是由于底层 API 造成的,遗憾的是这种方法是不可避免的。不过,如果您只需要基本的字符串读/写并且不想加载本机 DLL,它还是很方便的。
我相信你可以弄清楚如何使用它。
公共领域。玩得开心。
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);
有一天,Java 将有一个内置的 foreign function interface 以便于访问本机 API,而这种 hack 将是不必要的。
【讨论】:
【参考方案22】:回应 David answer - 我会做一些改进:
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;
【讨论】:
【参考方案23】:您可以使用 java 代码执行这些“REG QUERY”命令。
尝试从命令提示符执行此命令并从 java 代码执行命令。
HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
要搜索产品名称版本等详细信息,请使用 /v amd "name"。
HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v "ProductName"
【讨论】:
参考网址:- ***.com/questions/7112259/… 尝试从此代码执行您的“REG QUERY”。【参考方案24】:我更喜欢使用java.util.prefs.Preferences 类。
一个简单的例子是
// Write Operation
Preferences p = Preferences.userRoot();
p.put("key","value");
// also there are various other methods such as putByteArray(), putDouble() etc.
p.flush();
//Read Operation
Preferences p = Preferences.userRoot();
String value = p.get("key");
【讨论】:
这并不能真正回答问题。以上是关于使用 Java 读取/写入 Windows 注册表的主要内容,如果未能解决你的问题,请参考以下文章