使用Java读/写Windows注册表

使用Java读/写Windows注册表

Read/write to Windows registry using Java

如何使用Java读/写Windows注册表?


我知道这个问题已经过时了,但这是google上第一个"java read / write to registry"的搜索结果。最近我发现了这段令人惊奇的代码:

  • 可以读/写注册表的任何部分。
  • 不使用JNI。
  • 不使用任何第三方/外部应用程序。
  • 不使用WINDOWS API(直接)

这是纯Java代码。

它通过实际访问java.util.prefs.Preferences类中的私有方法来使用反射来工作。这个类的内部很复杂,但类本身很容易使用。

例如,以下代码从注册表获取确切的Windows分发:

1
2
3
4
5
String value = WinRegistry.readString (
    WinRegistry.HKEY_LOCAL_MACHINE,                             //HKEY
  "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",           //Key
  "ProductName");                                              //ValueName
    System.out.println("Windows Distribution =" + value);

这是原始课程。只需复制粘贴它,它应该工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
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;
  }
}

我无法找到并赞扬此代码的原作者。如果您发现任何详细信息,请添加评论,我将在此处添加。


您实际上并不需要第三方包。 Windows为所有注册表操作都有一个reg实用程序。要获取命令格式,请转到DOS propmt并键入:

1
reg /?

您可以通过Runtime类调用reg:

1
Runtime.getRuntime().exec("reg <your parameters here>");

使用上面的命令编辑密钥并添加新密钥很简单。要阅读注册表,您需要获得reg的输出,这有点棘手。这是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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:
            //
<Version information>

<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);
    }
}

Java Native Access(JNA)是一个用于处理本机库的优秀项目,并通过Advapi32Util和Advapi32支持平台库(platform.jar)中的Windows注册表。

更新:这里有一些代码片段,其中包含使用JNA 3.4.1使用JNA处理Windows注册表是多么容易的一些示例,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
"
, 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)
"
, 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");
    }
}

我增加了最初由David发布的Pure java代码,允许从64位JVM访问注册表的32位部分,反之亦然。我认为其他任何答案都没有解决这个问题。

这里是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
/**
 * 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;
  }
}


我在使用jRegistryKey之前已经完成了这个。它是一个LGPL Java / JNI库,可以满足您的需求。以下是我如何使用它通过regedit启用注册表编辑以及通过注册表在Windows中为自己启用"显示文件夹选项"选项的示例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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);
    }
}

}

是的,使用java.util.Preferences API,因为它的Windows实现使用Registry作为后端。

最后,它取决于您想要做什么:为您的应用程序存储首选项是首选项的功能。如果您想要实际更改与您的应用程序无关的注册表项,您将需要一些JNI应用程序,如Mark所述(此处无耻窃取):

From a quick google:
Check the WinPack for JNIWrapper. It has full Windows Registry access support including Reading and Writing.

The WinPack Demo has Registry Viewer implemented as an example.

Check at http://www.teamdev.com/jniwrapper/winpack/#registry_access

And...

There is also try JNIRegistry @ http://www.trustice.com/java/jnireg/

There is also the option of invoking an external app, which is responsible for reading / writing the registry.


从快速谷歌:

Check the WinPack for JNIWrapper. It
has full Windows Registry access
support including Reading and Writing.

The WinPack Demo has Registry Viewer
implemented as an example.

Check at
http://www.teamdev.com/jniwrapper/winpack/#registry_access

和...

There is also try JNIRegistry @
http://www.trustice.com/java/jnireg/

还可以选择调用外部应用程序,该应用程序负责读/写注册表。


这是Oleg解决方案的修改版本。我注意到在我的系统(Windows server 2003)上,"reg query"的输出不是由制表符(' t')分隔,而是由4个空格分隔。

我也简化了解决方案,因为不需要线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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:
      //
<Version information>

<key>    <registry type>    <value>




      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 == '
' || c == '
')
             break;
         sw.append(c);
         ++i;
      }

      return sw.toString();
  }
  catch (Exception e)
  {
      return null;
  }

}


如前所述,Preferences API使用注册表来存储首选项,但不能用于访问整个注册表。

然而,一个名叫David Croft的盗版者已经知道,可以使用Sun的Preferences API实现方法,从Java中读取Windows注册表而不使用JNI。这有一些危险,但值得一看。


很少有JNDI服务提供商可以使用Windows注册表。

人们可以观察http://java.sun.com/products/jndi/serviceproviders.html。


感谢原帖。我已经重新设计了这个实用程序类,并提出了它之前的缺陷,认为它可能会帮助其他人如此发布。我还添加了一些额外的实用方法。现在它能够读取Windows注册表中的任何文件(包括REG_DWORD,REG_BINARY,REG_EXPAND_SZ等)。所有的方法都像魅力一样。只需复制并粘贴即可。这是重新修改和修改的类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
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;
    }
}

使用方法的样本如下:

下面的方法从给定的路径中检索键的值:

1
String hex = WinRegistry.valueForKey(WinRegistry.HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update","AUOptions");

此方法检索指定路径的所有数据(以键和值的形式):

1
Map<String, String> map = WinRegistry.valuesForPath(WinRegistry.HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WSMAN");

此方法从给定路径以递归方式检索值:

1
String val = WinRegistry.valueForKeyPath(WinRegistry.HKEY_LOCAL_MACHINE,"System","TypeID");

并且这个从给定路径以递归方式检索所有值:

1
2
3
List<String> list = WinRegistry.valuesForKeyPath(
                   WinRegistry.HKEY_LOCAL_MACHINE,                  //HKEY                              "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall",   //path                "DisplayName"         //Key
            );

在上面的代码中,我检索了Windows系统中所有已安装的软件名称。
注意:请参阅这些方法的文档

这个检索给定路径的所有子键:

1
List<String> list3 = WinRegistry.subKeysForPath(WinRegistry.HKEY_CURRENT_USER,"Software");

重要说明:我在此过程中仅修改了阅读目的方法,而不是像createKey,deleteKey等编写目的方法。它们仍然与我收到的相同。


Preferences API方法不允许您访问注册表的所有分支。实际上,它只允许您访问Preferences API存储的位置,以及首选项。它不是像.NET那样的通用注册表处理API

如Mark所示,为了读取/写入每个键,我猜JNI或外部工具将是采用的方法。


写入寄存器的最佳方法可能是使用reg import本机Windows命令,并为其提供.reg文件的文件路径,该文件是通过从注册表导出内容生成的。

使用reg query命令完成读取。另见文档:
https://technet.microsoft.com/en-us/library/cc742028.aspx

因此,以下代码应该是不言自明的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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];
    }
}

你可以尝试WinRun4J。这是一个Windows java启动器和服务主机,但它还提供了一个用于访问注册表的库。

(顺便说一下我在这个项目上工作,如果你有任何问题,请告诉我)


java.util.prefs包为应用程序提供了一种存储和检索用户和系统首选项以及数据配置的方法。这些首选项数据将持久存储在存储的依赖于实现的后备中。例如在Windows操作系统中将存储在Windows注册表中。

要编写和读取这些数据,我们使用java.util.prefs.Preferences类。下面的代码显示了如何读取和写入注册表中的HKCUHKLM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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."));
    }
}

我以前对@ David的答案的编辑被拒绝了。以下是一些有用的信息。

这种"神奇"的作用是因为Sun将Windows的Preferences类实现为JDK的一部分,但它是包私有的。部分实现使用JNI。

  • 从JDK 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?


又一个图书馆......

https://code.google.com/p/java-registry/

这个启动reg.exe,读取/写入临时文件。我最终没有使用它,但它看起来像一个非常全面的实现。如果我确实使用它,我可能会潜入并添加一些更好的子进程管理。


这很疯狂......我从这里的一个帖子中取了代码,没看到还有18条评论,其中一条表明它没有读取dword值...

无论如何,我已经将那些代码的地狱重构为更少的ifs和方法......

Enum可以稍微改进一下,但是一旦我用自己的方式读取数值或字节数组而失败了,我就放弃了......

所以这里是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
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;
    }
}

注意:这不会读任何字符串但是!


The WinPack Demo has Registry Viewer
implemented as an example.

Check at
http://www.jniwrapper.com/winpack_features.jsp#registry

BTW,WinPack已移至以下地址:

http://www.teamdev.com/jniwrapper/winpack/


虽然这已经很老了,但我想在Windows平台上使用的更好的实用程序将是regini

单次调用流程:

1
Runtime.getRuntime().exec("regini <your script file abs path here>");

会做所有的魔术。我试过它,同时使用servany.exe将jar作为windows服务,这需要在注册表中进行更改以添加javaw.exe参数,并且它完美地工作。您可能希望阅读此内容:http://support.microsoft.com/kb/264584


这使用与David的答案中相同的Java内部API,但我已经完全重写了它。它现在更短,使用更好。我还添加了对HKEY_CLASSES_ROOT和其他配置单元的支持。它仍然有一些其他的限制(例如没有DWORD支持和没有Unicode支持),这是由于底层的API,并且这种方法遗憾地是不可避免的。但是,如果您只需要基本的字符串读/写并且不想加载本机DLL,那么它很方便。

我相信你可以弄清楚如何使用它。

公共区域。玩得开心。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
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将拥有一个内置的外部函数接口,可以轻松访问本机API,这种黑客攻击是不必要的。


您可以使用java代码执行这些"REG QUERY"命令。

尝试从命令提示符执行此操作并从java代码执行命令。

HKEY_LOCAL_MACHINE"SOFTWARE\Microsoft\Windows NT\CurrentVersion"

要搜索productname version等详细信息,请使用/ v amd"name"。

HKEY_LOCAL_MACHINE"SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v"ProductName"


回应大卫的回答 - 我会做一些改进:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
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;
    }
}

我更喜欢使用java.util.prefs.Preferences类。

一个简单的例子就是

1
2
3
4
5
6
7
8
// 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");


推荐阅读