我需要在C#中备份一个注册表项。我一直在尝试P / Invoke RegSaveKey无济于事。由于无法关闭的组策略设置,我无法使用“Reg.exe”备份注册表。
以下是所有代码:
private static UIntPtr GetKey(string registryPath)
{
UIntPtr hKey = UIntPtr.Zero;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, registryPath, 0, KEY_READ, out hKey) != 0)
{
throw new Exception("Error getting key!");
}
return hKey;
}
private static void ExportRegistry(string registryPath)
{
UIntPtr key = UIntPtr.Zero;
try
{
key = GetKey(registryPath);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return;
}
if (key == UIntPtr.Zero)
{
Console.WriteLine("Not key to export!");
return;
}
try
{
RegSaveKey(key, "c:\\temp\\test.reg", IntPtr.Zero);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
if (key != UIntPtr.Zero)
{
RegCloseKey(key);
}
}
private static int KEY_READ = 131097;
private static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern int RegCloseKey(UIntPtr hKey);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern uint RegSaveKey(UIntPtr hKey, string lpFile, IntPtr lpSecurityAttributes);
答案 0 :(得分:2)
您似乎没有检查RegOpenKeyEx或RegSaveKey的返回值是否有错误。我怀疑你得到的返回值为ERROR_PRIVILEGE_NOT_HELD。 Registry函数不使用SetLastError,它们直接返回它。与几乎每个Win32 API调用一样,必须检查返回值 。
无论您的ACL访问级别如何,RegSaveKey都需要启用SE_BACKUP_NAME权限。因此,您需要在调用RegSaveKey之前添加代码以启用此权限,然后在调用完成后将其禁用。
这是另一个question,其中包含更多信息,我确信还有其他信息。
答案 1 :(得分:1)
首先,我想评论一下,你的问题遗漏了一些非常重要的细节。也就是说,您实际上并未提供有关代码失败的任何信息。你所说的只是:
我一直试图P / Invoke RegSaveKey无济于事。
像这样的问题都与细节有关。我们需要查看精确而详细的错误诊断。请记住,我们无法看到您的屏幕。
您需要更加关注API调用的返回值。您正在检查RegOpenKeyEx
的返回值是否为零,但这就是全部。您需要捕获并检查RegOpenKeyEx
返回的值。这是一个错误代码。如果错误代码不等于零,您可以抛出Win32Exception
。
int err = RegOpenKeyEx(...);
if (err != 0)
throw new Win32Exception(err);
将代码更改为抛出Win32Exception
,并且在发生错误时至少会获得一些信息性文本。因此,如果RegOpenKeyEx
失败,您至少会找出原因。
您根本没有检查其他API调用。给他们同样的待遇。
您拨打RegOpenKeyEx
的失败模式非常少。我可以编写的唯一可信的解释是注册表项不存在。我希望你已经检查过了。但要注意registry redirector。如果您的进程是在64位操作系统上运行的32位进程,则重定向器将带您进入注册表的WOW6432Node
部分,即32位视图。也许你所说的“无济于事”是将信息保存到文件中,但这是错误的信息。这与注册表重定向器让您感到困惑是一致的。
如果这是咬你的,那么在致电KEY_WOW64_64KEY
时请加上RegOpenKeyEx
标志。或者定位x64。
使用RegistryKey
打开密钥要容易得多。我知道你不能轻易打电话给RegSaveKey
所以你仍然需要调用它。但是RegistryKey
会公开Handle
属性,您可以传递给RegSaveKey
。这有一个附带条件。如果您确实需要使用KEY_WOW64_64KEY
标志,则需要.net 4和RegistryView
。
至于RegSaveKey
,我会按照斯蒂芬在答案中提供的信息。