写在前面
正常C#实现导出注册表的键值可以用 Process类库 呼起 regedit.exe 的方式直接导出.reg 文件;代码如下:
// HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\xxx
private static void ExportReg(string exportPath, string registryPath)
{
string path = "\""+ exportPath + "\"";
string key = "\""+ registryPath + "\"";
using (Process proc = new Process())
{
try
{
proc.StartInfo.FileName = "regedit.exe";
proc.StartInfo.UseShellExecute = false;
proc = Process.Start("regedit.exe", "/e " + path + " "+ key);
proc.WaitForExit();
}
catch (Exception ex)
{
// 处理异常
Console.WriteLine(ex.Message);
}
}
}
为了测试此前的注册表操作工具类和yaml操作工具类,就不用这种方式了,因为后续将需要做注册表的键值快照以便做比对。
通过自行遍历键值的方式也可以更深入的了解注册表的数据存储结构。
代码实现
private void TestMethod()
{
var targetKey = "MongoDB";
var targetDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "key_files");
if (!Directory.Exists(targetDir))
{
Directory.CreateDirectory(targetDir);
}
var controlSet001Key = RegistryHelper.GetRegistryKey(@"SYSTEM\ControlSet001\Services");
var currentControlSetKey = RegistryHelper.GetRegistryKey(@"SYSTEM\CurrentControlSet\Services");
if (controlSet001Key != null)
{
var subKeyNames = controlSet001Key.GetSubKeyNames();
if (subKeyNames.Contains(targetKey))
{
// 提取对应的子级键值
var targetKeyItem = GetKeyItem(controlSet001Key, targetKey);
var filePath = Path.Combine(targetDir, $"{targetKey}.yml");
YamlHelper.SerializeToFile(targetKeyItem, filePath);
}
controlSet001Key.Close();
}
if (currentControlSetKey != null)
{
var subKeyNames = currentControlSetKey.GetSubKeyNames();
if (subKeyNames.Contains(targetKey))
{
// 提取对应的子级键值
var targetKeyItem = GetKeyItem(currentControlSetKey, targetKey);
var filePath = Path.Combine(targetDir, $"{targetKey}_current.yml");
YamlHelper.SerializeToFile(targetKeyItem, filePath);
}
currentControlSetKey.Close();
}
}
private KeyItem GetKeyItem(RegistryKey parent, string key)
{
var subKeyItem = parent.OpenSubKey(key);
if (subKeyItem == null)
return null;
var keyItemConfig = new KeyItem();
keyItemConfig.Name = key;
var subKeyNames = subKeyItem.GetSubKeyNames();
if (subKeyNames.Length > 0)
{
keyItemConfig.Children = new List<KeyItem>();
foreach (var subKey in subKeyNames)
{
var subItem = GetKeyItem(subKeyItem, subKey);
if (subItem == null) continue;
keyItemConfig.Children.Add(subItem);
}
}
if (subKeyItem.ValueCount > 0)
{
if (keyItemConfig.Children == null)
keyItemConfig.Children = new List<KeyItem>();
FillSubValues(subKeyItem, keyItemConfig);
}
return keyItemConfig;
}
private void FillSubValues(RegistryKey registryKey, KeyItem keyItem)
{
var valueNames = registryKey.GetValueNames();
foreach (var valueName in valueNames)
{
var valueItem = new KeyItem();
valueItem.Name = valueName;
var value = registryKey.GetValue(valueName);
if (value != null)
valueItem.Value = value.ToString();
valueItem.Type = (int)registryKey.GetValueKind(valueName);
keyItem.Children.Add(valueItem);
}
}
数据结构:
public class KeyItem
{
[YamlMember(Alias = "name")]
public string Name { get; set; }
[YamlMember(Alias = "value")]
public string Value { get; set; }
[YamlMember(Alias = "type")]
public int Type { get; set; }
[YamlMember(Alias = "children")]
public List<KeyItem> Children { get; set; }
}
操作结果
name: MongoDB
value:
type: 0
children:
- name: Type
value: 16
type: 4
children:
- name: Start
value: 3
type: 4
children:
- name: ErrorControl
value: 1
type: 4
children:
- name: ImagePath
value: E:\MongoDb\3.2\bin\mongod.exe --logpath E:\MongoDb\3.2\logs\MongoDB.log --logappend --auth --dbpath E:\MongoDb\3.2\data --directoryperdb --service
type: 2
children:
- name: DisplayName
value: MongoDB
type: 1
children:
- name: ObjectName
value: LocalSystem
type: 1
children:
- name: Description
value: MongoDB Server
type: 1
children:
- name: PreshutdownTimeout
value: 600000
type: 4
children:
本文介绍了如何使用C#编程语言,通过遍历Windows注册表,尤其是HKEY_LOCAL_MACHINE下的键值,实现对注册表的深入理解和数据结构的保存,包括使用YAML格式将注册表内容持久化到文件中。
267

被折叠的 条评论
为什么被折叠?



