重庆sem优化百度快照优化排名
以下是通过 JNI 实现对 Windows 注册表的增删改查操作的完整示例,包含详细注释和步骤说明:
JNI
一、Java 类声明(包含 Native 方法)
public class RegistryHelper {// 声明 Native 方法public native boolean createRegistryKey(String rootPath, String keyName);public native boolean setValue(String rootPath, String keyName, String valueName, String valueData);public native String getValue(String rootPath, String keyName, String valueName);public native boolean deleteValue(String rootPath, String keyName, String valueName);public native boolean deleteKey(String rootPath, String keyName);static {System.loadLibrary("RegistryJNILib"); // 加载本地库(DLL)}
}
二、JNI 实现(C++ 代码)
#include <windows.h>
#include <jni.h>
#include <string>
#include "RegistryHelper.h" // 通过 javah 生成的头文件// 辅助函数:将 Java String 转换为 Unicode 字符串
std::wstring jstringToWString(JNIEnv *env, jstring jstr) {const jchar* chars = env->GetStringChars(jstr, nullptr);std::wstring wstr((wchar_t*)chars, env->GetStringLength(jstr));env->ReleaseStringChars(jstr, chars);return wstr;
}// 1. 创建注册表键
JNIEXPORT jboolean JNICALL Java_RegistryHelper_createRegistryKey(JNIEnv *env, jobject obj, jstring rootPath, jstring keyName) {// 转换参数为 Unicodestd::wstring wRoot = jstringToWString(env, rootPath);std::wstring wKey = jstringToWString(env, keyName);HKEY hKey;LONG result = RegCreateKeyExW((HKEY)std::stoul(wRoot), // 将根路径字符串转为 HKEY(如 "0x80000002" 对应 HKEY_LOCAL_MACHINE)wKey.c_str(), // 键路径0,nullptr,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,nullptr,&hKey,nullptr);RegCloseKey(hKey); // 关闭句柄return (result == ERROR_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}// 2. 设置注册表值
JNIEXPORT jboolean JNICALL Java_RegistryHelper_setValue(JNIEnv *env, jobject obj, jstring rootPath, jstring keyName, jstring valueName, jstring valueData) {std::wstring wRoot = jstringToWString(env, rootPath);std::wstring wKey = jstringToWString(env, keyName);std::wstring wValue = jstringToWString(env, valueName);std::wstring wData = jstringToWString(env, valueData);HKEY hKey;LONG resultOpen = RegOpenKeyExW((HKEY)std::stoul(wRoot),wKey.c_str(),0,KEY_SET_VALUE,&hKey);if (resultOpen != ERROR_SUCCESS) {return JNI_FALSE;}LONG resultSet = RegSetValueExW(hKey,wValue.c_str(),0,REG_SZ,(const BYTE*)wData.c_str(),(wData.size() + 1) * sizeof(wchar_t));RegCloseKey(hKey);return (resultSet == ERROR_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}// 3. 获取注册表值
JNIEXPORT jstring JNICALL Java_RegistryHelper_getValue(JNIEnv *env, jobject obj, jstring rootPath, jstring keyName, jstring valueName) {std::wstring wRoot = jstringToWString(env, rootPath);std::wstring wKey = jstringToWString(env, keyName);std::wstring wValue = jstringToWString(env, valueName);HKEY hKey;LONG resultOpen = RegOpenKeyExW((HKEY)std::stoul(wRoot),wKey.c_str(),0,KEY_QUERY_VALUE,&hKey);if (resultOpen != ERROR_SUCCESS) {return nullptr;}DWORD type = 0;DWORD dataSize = 0;RegQueryValueExW(hKey,wValue.c_str(),nullptr,&type,nullptr,&dataSize // 获取数据长度);if (type != REG_SZ) { // 仅处理字符串类型RegCloseKey(hKey);return nullptr;}std::wstring buffer(dataSize / sizeof(wchar_t), L'\0');RegQueryValueExW(hKey,wValue.c_str(),nullptr,nullptr,(LPBYTE)buffer.data(),&dataSize);RegCloseKey(hKey);return env->NewStringUTF(buffer.c_str()); // 转换为 UTF-8 返回
}// 4. 删除注册表值
JNIEXPORT jboolean JNICALL Java_RegistryHelper_deleteValue(JNIEnv *env, jobject obj, jstring rootPath, jstring keyName, jstring valueName) {std::wstring wRoot = jstringToWString(env, rootPath);std::wstring wKey = jstringToWString(env, keyName);std::wstring wValue = jstringToWString(env, valueName);HKEY hKey;LONG resultOpen = RegOpenKeyExW((HKEY)std::stoul(wRoot),wKey.c_str(),0,KEY_SET_VALUE,&hKey);if (resultOpen != ERROR_SUCCESS) {return JNI_FALSE;}LONG result = RegDeleteValueW(hKey, wValue.c_str());RegCloseKey(hKey);return (result == ERROR_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}// 5. 删除注册表键
JNIEXPORT jboolean JNICALL Java_RegistryHelper_deleteKey(JNIEnv *env, jobject obj, jstring rootPath, jstring keyName) {std::wstring wRoot = jstringToWString(env, rootPath);std::wstring wKey = jstringToWString(env, keyName);LONG result = RegDeleteKeyW((HKEY)std::stoul(wRoot),wKey.c_str());return (result == ERROR_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}
三、关键代码说明
1. 参数转换
-
根路径处理:Java 字符串如
"0x80000002"
(对应HKEY_LOCAL_MACHINE
)需转换为HKEY
类型:(HKEY)std::stoul(wRoot)
-
Unicode 转换:注册表 API 使用宽字符(Unicode),需将 Java 字符串转换为
std::wstring
:std::wstring jstringToWString(JNIEnv *env, jstring jstr) { ... }
2. 错误处理
-
返回值检查:每个注册表操作均检查返回值是否为
ERROR_SUCCESS
:if (result != ERROR_SUCCESS) return JNI_FALSE;
-
异常抛出:在 Java 层可通过
throws Exception
捕获失败情况。
3. 注册表操作函数
- 创建键:
RegCreateKeyExW
- 打开键:
RegOpenKeyExW
- 设置值:
RegSetValueExW
- 查询值:
RegQueryValueExW
- 删除值:
RegDeleteValueW
- 删除键:
RegDeleteKeyW
四、使用示例
public class Main {public static void main(String[] args) {RegistryHelper helper = new RegistryHelper();// 创建键boolean created = helper.createRegistryKey("0x80000002", "SOFTWARE\\MyApp");System.out.println("Key created: " + created);// 设置值boolean setValueSuccess = helper.setValue("0x80000002","SOFTWARE\\MyApp","TestValue","Hello JNI");System.out.println("Value set: " + setValueSuccess);// 获取值String value = helper.getValue("0x80000002","SOFTWARE\\MyApp","TestValue");System.out.println("Value: " + value);// 删除值boolean deleteValueSuccess = helper.deleteValue("0x80000002","SOFTWARE\\MyApp","TestValue");System.out.println("Value deleted: " + deleteValueSuccess);// 删除键boolean deleteKeySuccess = helper.deleteKey("0x80000002","SOFTWARE\\MyApp");System.out.println("Key deleted: " + deleteKeySuccess);}
}
五、编译与运行
-
生成头文件:
javac RegistryHelper.java javah -jni RegistryHelper
-
编译 C++ 代码为 DLL(需 Visual Studio 或 MinGW):
cl /I"%JAVA_HOME%\include" /I"%JAVA_HOME%\include\win32" RegistryHelper.cpp /link -dll -out:RegistryJNILib.dll
-
运行 Java 程序:
java -Djava.library.path=. Main
六、注意事项
-
权限问题:
- 修改注册表通常需要管理员权限,需以管理员身份运行程序。
-
路径格式:
- 根路径需为
HKEY
值的十六进制字符串(如"0x80000002"
对应HKEY_LOCAL_MACHINE
)。
- 根路径需为
-
Unicode 支持:
- 所有字符串操作均使用宽字符(
wchar_t
)确保兼容性。
- 所有字符串操作均使用宽字符(
通过此示例,可以实现对 Windows 注册表的完整增删改查操作,适用于配置管理、插件开发等场景。
以下是使用纯 Java 通过系统命令调用 Windows 注册表工具 reg.exe
实现增删改查操作的示例代码,包含详细注释和使用说明:
纯Java
一、Java 实现类
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;public class RegistryManager {// 执行系统命令的通用方法private static boolean executeCommand(String command) {try {Process process = Runtime.getRuntime().exec(command);int exitCode = process.waitFor();return exitCode == 0;} catch (IOException | InterruptedException e) {e.printStackTrace();return false;}}// 1. 创建注册表键public static boolean createRegistryKey(String root, String keyPath) {String command = String.format("reg add \"%s\\%s\" /f", root, keyPath);return executeCommand(command);}// 2. 设置注册表值public static boolean setValue(String root, String keyPath, String valueName, String valueData) {String command = String.format("reg add \"%s\\%s\" /v \"%s\" /t REG_SZ /d \"%s\" /f",root, keyPath, valueName, valueData);return executeCommand(command);}// 3. 获取注册表值public static String getValue(String root, String keyPath, String valueName) {String command = String.format("reg query \"%s\\%s\" /v \"%s\"",root, keyPath, valueName);try {Process process = Runtime.getRuntime().exec(command);BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {if (line.contains(valueName)) {// 提取值数据(最后一段)String[] parts = line.split("\\s+");if (parts.length >= 4) {return parts[parts.length - 1];}}}process.waitFor();} catch (IOException | InterruptedException e) {e.printStackTrace();}return null;}// 4. 删除注册表值public static boolean deleteValue(String root, String keyPath, String valueName) {String command = String.format("reg delete \"%s\\%s\" /v \"%s\" /f",root, keyPath, valueName);return executeCommand(command);}// 5. 删除注册表键(需确保键为空)public static boolean deleteKey(String root, String keyPath) {String command = String.format("reg delete \"%s\\%s\" /f", root, keyPath);return executeCommand(command);}
}
二、使用示例
public class Main {public static void main(String[] args) {String root = "HKEY_LOCAL_MACHINE"; // 注册表根键String keyPath = "SOFTWARE\\MyApp"; // 注册表键路径String valueName = "TestValue"; // 值名称String valueData = "Hello Java"; // 值数据// 1. 创建键boolean created = RegistryManager.createRegistryKey(root, keyPath);System.out.println("Key created: " + created);// 2. 设置值boolean setValueSuccess = RegistryManager.setValue(root, keyPath, valueName, valueData);System.out.println("Value set: " + setValueSuccess);// 3. 获取值String retrievedValue = RegistryManager.getValue(root, keyPath, valueName);System.out.println("Retrieved Value: " + retrievedValue);// 4. 删除值boolean deleteValueSuccess = RegistryManager.deleteValue(root, keyPath, valueName);System.out.println("Value deleted: " + deleteValueSuccess);// 5. 删除键(需确保键为空)boolean deleteKeySuccess = RegistryManager.deleteKey(root, keyPath);System.out.println("Key deleted: " + deleteKeySuccess);}
}
三、关键代码说明
1. 命令执行逻辑
executeCommand
方法:
通过Runtime.exec
执行命令,并通过waitFor()
等待命令完成。
成功返回true
(exitCode == 0
),失败返回false
。
2. 注册表操作命令
-
创建键:
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\MyApp" /f
/f
表示强制覆盖(忽略确认提示)。
-
设置值:
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\MyApp" /v "TestValue" /t REG_SZ /d "Hello Java" /f
/v
指定值名称,/t
指定类型(REG_SZ
表示字符串),/d
指定值数据。
-
查询值:
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\MyApp" /v "TestValue"
- 解析输出流中的值(如
Hello Java
)。
- 解析输出流中的值(如
-
删除值/键:
reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\MyApp" /v "TestValue" /f
reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\MyApp" /f
/f
强制删除。
3. 注意事项
-
权限要求:
- 修改注册表需管理员权限,需以管理员身份运行 Java 程序。
-
路径格式:
- 注册表路径需以根键开头(如
HKEY_LOCAL_MACHINE
)。
- 注册表路径需以根键开头(如
-
值类型限制:
- 示例默认使用
REG_SZ
类型(字符串),其他类型(如REG_DWORD
)需修改命令参数。
- 示例默认使用
-
错误处理:
- 命令执行失败时,可通过
process.getErrorStream()
获取错误信息。
- 命令执行失败时,可通过
四、输出示例
Key created: true
Value set: true
Retrieved Value: Hello Java
Value deleted: true
Key deleted: true
五、扩展建议
-
支持其他值类型:
修改命令中的/t
参数,例如REG_DWORD
(32位整数):String command = String.format("reg add \"%s\\%s\" /v \"%s\" /t REG_DWORD /d 0x12345678 /f",root, keyPath, valueName );
-
异常封装:
将IOException
和InterruptedException
封装为自定义异常,提高可维护性。 -
异步执行:
使用CompletableFuture
或线程池异步执行命令,避免阻塞主线程。
通过此方案,可在纯 Java 环境中实现对 Windows 注册表的简单操作,适用于配置管理、系统集成等场景。