чтение / запись в реестр windows с помощью java

<p>как можно читать/записывать в реестр windows, используя java?</p>

<p>я знаю, что этот вопрос старый, но это первый результат поиска в google "java для чтения/записи в реестр". недавно я нашел этот удивительный кусок кода, который:</p><ul> <li>может читать/писать в любой части реестра.</li> <li>не использует jni.</li> <li>не использует любую 3-й сторону/внешние заявки на работу.</li> <li>не использует api-интерфейс windows (напрямую)</li> </ul><p>это чистый код java.</p><p>он использует отражение для работы, фактически получая доступ к закрытым методам в классе <code>java.util.prefs.preferences</code>. внутренние элементы этого класса сложны, но сам класс очень прост в использовании.</p><p>например, следующий код получает точное распределение windows <strong>из реестра</strong>:</p><pre><code>string value = winregistry.readstring ( winregistry.hkey\_local\_machine, //hkey "software\\microsoft\\windows nt\\currentversion", //key "productname"); //valuename system.out.println("windows distribution = " + value); </code></pre><p>вот оригинальный класс. просто скопируйте и вставьте его, и оно должно работать:</p><pre><code>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; } } </code></pre><p>я не смог найти и отдать должное первоначальному автору этого кода. если вы найдете какие-либо подробности, пожалуйста, добавьте комментарий, и я добавлю его здесь.</p>

<p>вам на самом деле не нужен сторонний пакет. в windows есть утилита reg для всех операций реестра. чтобы получить формат команды, перейдите в dos propmt и введите:</p><pre><code>reg /? </code></pre><p>вы можете вызвать <em>reg</em> через класс runtime:</p><pre><code>runtime.getruntime().exec("reg <your parameters here>"); </code></pre><p>редактировать ключи и добавлять новые очень просто, используя команду выше. чтобы прочитать реестр, вам нужно получить вывод <em>reg</em>, и это немного сложно. вот код:</p><pre><code>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); } } </code></pre><hr>

<p> <a href="https://github.com/twall/jna">java native access (jna)</a> является отличным проектом для работы с собственными библиотеками и поддерживает реестр windows в библиотеке платформы (platform.jar) через <a href="http://jna.java.net/javadoc/platform/com/sun/jna/platform/win32/advapi32util.html">advapi32util</a> и - <a href="http://jna.java.net/javadoc/platform/com/sun/jna/platform/win32/advapi32.html">advapi32</a> .</p><p><strong> обновление: </strong> вот фрагмент с некоторыми примерами того, как легко использовать jna для работы с реестром windows с использованием jna 3.4.1,</p><pre><code>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\\stackoverflow"); advapi32util.registrysetstringvalue(winreg.hkey\_current\_user, "software\\stackoverflow", "url", "http://stackoverflow.com/a/6287763/277307"); // delete a key advapi32util.registrydeletekey(winreg.hkey\_current\_user, "software\\stackoverflow"); } } </code></pre>

<p>я увеличил код pure java, первоначально опубликованный дэвидом, чтобы разрешить доступ к 32-битной секции реестра из 64-битной jvm, и наоборот. я не думаю, что какие-либо другие ответы касаются этого.</p><p>вот:</p><pre><code>/** * 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; } } </code></pre>

<p>я сделал это перед использованием <a href="http://sourceforge.net/projects/jregistrykey/">jregistrykey</a> . это библиотека lgpl java/jni, которая может делать то, что вам нужно. вот пример того, как я использовал его, чтобы включить редактирование реестра с помощью regedit, а также параметр "показать параметры папки" для себя в windows через реестр.</p><pre><code>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); } } } </code></pre>

<p>да, используя api java.util.preferences, поскольку его реализация в windows использует реестр в качестве бэкэнда.</p><p>в конце концов, это зависит от того, что вы хотите сделать: сохранение настроек для вашего приложения - это то, что настройки делают просто великолепно. если вы действительно хотите изменить разделы реестра, не связанные с вашим приложением, вам понадобится какое-то приложение jni, как описано марком (бесстыдная кража здесь):</p><blockquote> <p>из быстрого google: проверьте winpack для jniwrapper. он имеет полную поддержку доступа к реестру windows, включая чтение и запись.</p> <p>в качестве примера в демоверсии winpack реализована программа просмотра реестра.</p> <p>проверьте по адресу <a href="http://www.teamdev.com/jniwrapper/winpack/#registry\_access">http://www.teamdev.com/jniwrapper/winpack/#registry\_access</a> </p> <p>а также...</p> <p>там же попробуйте jniregistry @ <a href="http://www.trustice.com/java/jnireg/">http://www.trustice.com/java/jnireg/</a> </p> <p>существует также возможность вызова внешнего приложения, которое отвечает за чтение/запись реестра.</p> </blockquote>

<p>из быстрого google:</p><blockquote> <p>проверьте winpack для jniwrapper. он имеет полную поддержку доступа к реестру windows, включая чтение и запись.</p> <p>в качестве примера в демоверсии winpack реализована программа просмотра реестра.</p> <p>проверьте по адресу <a href="http://www.teamdev.com/jniwrapper/winpack/#registry\_access">http://www.teamdev.com/jniwrapper/winpack/#registry\_access</a> </p> </blockquote><p>а также...</p><blockquote> <p>там же попробуйте jniregistry @ <a href="http://www.trustice.com/java/jnireg/">http://www.trustice.com/java/jnireg/</a> </p> </blockquote><p>существует также возможность вызова внешнего приложения, которое отвечает за чтение/запись реестра.</p>

<p>вот модифицированная версия решения олега. я заметил, что в моей системе (windows server 2003) вывод "reg query" разделен не табуляцией ('\ t'), а 4 пробелами.</p><p>я также упростил решение, так как поток не требуется.</p><pre><code>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; } </code></pre><p>}</p>

<p>как было отмечено, api настроек использует реестр для хранения настроек, но не может использоваться для доступа ко всему реестру.</p><p>однако пират по имени дэвид крофт выяснил, что в реализации sun preferences api можно использовать методы для <a href="http://www.davidc.net/programming/java/reading-windows-registry-java-without-jni">чтение реестра windows из java без jni</a> . в этом есть некоторые опасности, но на это стоит посмотреть.</p>

<p>есть несколько поставщиков услуг jndi для работы с реестром windows.</p><p>можно было наблюдать <a href="https://web.archive.org/web/20120801053337/http://java.sun.com/products/jndi/serviceproviders.html">http://java.sun.com/products/jndi/serviceproviders.html</a> .</p>

<p>благодаря оригинальному сообщению. я переназначил этот служебный класс и обнаружил недостатки, которые у него были ранее, подумал, что это может помочь другим, поэтому выкладывать здесь. я также добавил несколько дополнительных утилитарных методов. теперь он может читать любой файл в реестре windows (включая reg\_dword, reg\_binary, reg\_expand\_sz и т.д.). все методы работают как шарм. просто скопируйте и вставьте его, и оно должно работать. вот пересмотренный и измененный класс:</p><pre><code>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; } } </code></pre><p><strong>пример использования методов следующий:</strong></p><p>метод ниже извлекает значение ключа из заданного пути:</p><pre><code>string hex = winregistry.valueforkey(winregistry.hkey\_local\_machine, "software\\microsoft\\windows\\currentversion\\windowsupdate\\auto update", "auoptions"); </code></pre><p>этот метод извлекает все данные по указанному пути (в виде ключей и значений):</p><pre><code>map<string, string> map = winregistry.valuesforpath(winregistry.hkey\_local\_machine, "software\\microsoft\\windows\\currentversion\\wsman"); </code></pre><p>этот метод возвращает значение рекурсивно для ключа по заданному пути:</p><pre><code>string val = winregistry.valueforkeypath(winregistry.hkey\_local\_machine, "system", "typeid"); </code></pre><p>и этот извлекает все значения рекурсивно для ключа из данного пути:</p><pre><code>list<string> list = winregistry.valuesforkeypath( winregistry.hkey\_local\_machine, //hkey "software\\wow6432node\\microsoft\\windows\\currentversion\\uninstall", //path "displayname" //key ); </code></pre><p>здесь, в приведенном выше коде, я получил все установленные имена программ в системе windows.<br> <strong>примечание: см. документацию по этим методам</strong></p><p>и этот извлекает все подключи данного пути:</p><pre><code>list<string> list3 = winregistry.subkeysforpath(winregistry.hkey\_current\_user, "software"); </code></pre><p><strong>важное примечание: в этом процессе я изменил только методы назначения чтения, а не методы назначения записи, такие как createkey, deletekey и т.д. они все такие же, как я их получил.</strong></p>

<p>вероятно, лучший способ записи в регистр - это использование собственной команды windows <code>reg import</code> и указание пути к файлу <code>.reg</code>, который был сгенерирован путем экспорта чего-либо из реестра.</p><p>чтение выполняется командой <code>reg query</code>. также см. документацию: <a href="https://technet.microsoft.com/en-us/library/cc742028.aspx">https://technet.microsoft.com/en-us/library/cc742028.aspx</a> </p><p>поэтому следующий код должен быть понятен:</p><pre><code>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]; } } </code></pre>

<p>подход api настроек не дает вам доступа ко всем веткам реестра. фактически, он дает вам доступ только к тому месту, где preferences api хранит свои, ну, предпочтения. это не универсальный api обработки реестра, как в .net</p><p>я полагаю, что для чтения/записи каждого ключа, как показывает марк, подход jni или внешний инструмент.</p>

<p>вы можете попробовать <a href="http://winrun4j.sourceforge.net/">winrun4j</a> . это средство запуска windows java и узел службы, но оно также предоставляет библиотеку для доступа к реестру.</p><p>(кстати, я работаю над этим проектом, поэтому дайте мне знать, если у вас есть какие-либо вопросы)</p>

<p>пакет <code>java.util.prefs</code> позволяет приложениям сохранять и извлекать пользовательские и системные настройки и конфигурацию данных. эти данные о предпочтениях будут постоянно храниться в зависимой от реализации резервной копии. например, в операционной системе windows в будет храниться в реестре windows.</p><p>для записи и чтения этих данных мы используем класс <code>java.util.prefs.preferences</code>. ниже приведен код, показывающий, как читать и записывать <code>hkcu</code> и <code>hklm</code> в реестре.</p><pre><code>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.")); } } </code></pre>

<p>мое предыдущее изменение ответа @ david было отклонено. вот некоторая полезная информация об этом.</p><p>эта "магия" работает, потому что sun реализует класс <code>preferences</code> для windows как часть jdk, но это <a href="http://docs.oracle.com/javase/tutorial/java/javaoo/accesscontrol.html">пакет private</a> . части реализации используют jni.</p><ul> <li>пакетный закрытый класс из jdk <code>java.util.prefs.windowspreferences</code>: <a href="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/windowspreferences.java</a> знак равно</li> <li>jni: <a href="http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/windows/native/java/util/windowspreferences.c">http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/windows/native/java/util/windowspreferences.c</a> </li> </ul><p>реализация выбирается во время выполнения с использованием заводского метода здесь: <a href="http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/util/prefs/preferences.java#preferences.0factory">http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/util/prefs/ preferences.java # preferences.0factory</a> </p><p>реальный вопрос: почему openjdk не предоставляет этот api публично?</p>

<p>еще одна библиотека ...</p><p> <a href="https://code.google.com/p/java-registry/">https://code.google.com/p/java-registry/</a> </p><p>этот запускает reg.exe под крышками, чтение/запись во временные файлы. я не заканчивал тем, что использовал это, но это похоже на довольно всестороннюю реализацию. если бы я использовал его, я мог бы погрузиться и добавить немного лучшего управления дочерними процессами.</p>

<blockquote> <p>в качестве примера в демоверсии winpack реализована программа просмотра реестра.</p> <p>проверьте по адресу <a href="http://www.jniwrapper.com/winpack\_features.jsp#registry">http://www.jniwrapper.com/winpack\_features.jsp#registry</a> </p> </blockquote><p>кстати, winpack был перемещен по следующему адресу:</p><p> <a href="http://www.teamdev.com/jniwrapper/winpack/">http://www.teamdev.com/jniwrapper/winpack/</a> </p>

<p>хотя это довольно старое, но я думаю, что лучшая утилита для использования на платформе windows будет <code>regini</code>:</p><p>один вызов для обработки:</p><pre><code>runtime.getruntime().exec("regini <your script file abs path here>"); </code></pre><p>сделает всю магию. я попробовал это, делая jar как службу windows, используя servany.exe, который требует внесения изменений в реестр для добавления аргументов javaw.exe, и он работает отлично. возможно, вы захотите прочитать это: <a href="http://support.microsoft.com/kb/264584">http://support.microsoft.com/kb/264584</a> </p>

<p>это было сумасшествие ... я взял код из одного из постов здесь, не смог увидеть еще 18 комментариев, в которых говорилось, что он не читает значение dword ...</p><p>в любом случае, я преобразил адский код в нечто с меньшим количеством ifs и методов ...</p><p>enum можно немного улучшить, но как только я попытался прочитать числовое значение или байтовый массив и потерпел неудачу, я сдался ...</p><p>итак, вот оно:</p><pre><code>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; } } </code></pre><p><strong>примечание: это ничего не читает, но почему строки !!!!!</strong></p>