在C#中查找和删除注册表项

时间:2013-08-30 09:38:49

标签: c# key registry

我正在寻找一个可以找到注册表项并删除它的脚本。 我的关键是:“{24EAA2C1-3EE7-40E0-AEA3-D20AA14A6005}”。 这个密钥存储在很多地方:

HKEY_CLASSES_ROOT\CLSID\{MY_KEY}
HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{MY_KEY}
HKEY_CURRENT_USER\Software\Classes\CLSID\{MY_KEY}
HKEY_CURRENT_USER\Software\Classes\Wow6432Node\CLSID\{MY_KEY}
HKEY_USERS\S-1-5-21-1786904987-2011555162-1551513139-1001\Software\Classes\CLSID\{MY_KEY}
HKEY_USERS\S-1-5-21-1786904987-2011555162-1551513139-1001\Software\Classes\Wow6432Node\CLSID\{KEY}
HKEY_USERS\S-1-5-21-1786904987-2011555162-1551513139-1001_Classes\CLSID\{MY_KEY}
HKEY_USERS\S-1-5-21-1786904987-2011555162-1551513139-1001_Classes\Wow6432Node\CLSID\{MY_KEY}

但这些位置可能会有所不同(这就是为什么我必须在删除它们之前找到它们)。 我想使用C#脚本(在控制台应用程序中)删除此密钥的每个出现

我试过了:

static void Main(string[] args)
{
    DeleteKeyTest("{MY_KEY}");
}

private RegistryKey baseRegistryKey = Registry.ClassesRoot;
public void DeleteKeyTest(string KeyName)
{
    try
    {
        RegistryKey rk = baseRegistryKey;
        rk.DeleteSubKey(KeyName);       
    }
    catch (Exception e)
    {
    }
}

我收到错误:

  

无法删除子密钥,因为它不存在。

修改

这是我的代码,用于查找密钥的所有出现:

public List<string> SearchKey(string Key)
{
    List<string> ListKeys = getKeyPath(Key, RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64));
    ListKeys.AddRange(getKeyPath(Key, RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64)));
    ListKeys.AddRange(getKeyPath(Key, RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)));
    ListKeys.AddRange(getKeyPath(Key, RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Registry64)));
    ListKeys.AddRange(getKeyPath(Key, RegistryKey.OpenBaseKey(RegistryHive.CurrentConfig, RegistryView.Registry64)));
    return ListKeys;
}

private List<string> getKeyPath(string key, RegistryKey registryKey)
{
    List<string> keys = new List<string>();
    if (CanReadRegistryKey(registryKey))
    {
        foreach (string keyname in registryKey.GetSubKeyNames())
        {
            if (keyname.Contains(key))
                keys.Add(registryKey.Name + "\\" + keyname);

            if (CanReadKey(registryKey, keyname))
                keys.AddRange(getKeyPath(key, registryKey.OpenSubKey(keyname, RegistryKeyPermissionCheck.ReadSubTree)));
        }
    }
    return keys;
}

private bool CanReadRegistryKey(RegistryKey registryKey)
{
    try
    {
        registryKey.GetSubKeyNames();
        return true;
    }
    catch (UnauthorizedAccessException e)
    {
        return false;
    }
}

private bool CanReadKey(RegistryKey registryKey, string keyname)
{
    try
    {
        registryKey.OpenSubKey(keyname, RegistryKeyPermissionCheck.ReadSubTree);
        return true;
    }
    catch (SecurityException e)
    {
        return false;
    }
}

用法:

List<string> ListKeys = SearchKey("MY_KEY");

我并不总是得到相同的结果。有时我会找到7个密钥,有时是8.(缺少的密钥是HKEY_CLASSES_ROOT \ Wow6432Node \ CLSID {MY_KEY})

以下是我的删除代码:

public int RemoveKey(string Key)
{
    int count = RemoveKeys(Key, RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Registry64));
    count += RemoveKeys(Key, RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64));
    count += RemoveKeys(Key, RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64));
    count += RemoveKeys(Key, RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Registry64));
    count += RemoveKeys(Key, RegistryKey.OpenBaseKey(RegistryHive.CurrentConfig, RegistryView.Registry64));
    return count;
}

private int RemoveKeys(string key, RegistryKey registryKey)
{
    int count = 0;
    if (CanReadRegistryKey(registryKey))
    {
        foreach (string keyname in registryKey.GetSubKeyNames())
        {
            count += RemoveKeys(key, registryKey.OpenSubKey(keyname));
            try
            {
                if (keyname.Contains(key))
                {
                    registryKey.DeleteValue(keyname);
                    count++;
                }
            }
            catch (Exception e)
            {
            }
        }
    }
    return count;
}

用法:

int NumberOfRemovedKeys = RemoveKey("MY_KEY");

但我总是在这段代码上出错:

registryKey.DeleteValue(keyname);

错误讯息:

  

System.UnauthorizedAccessException:无法写入注册表项。

当我尝试以管理员模式启动应用程序时,我遇到了同样的错误。 但是当我尝试从注册表中删除manualy键时,没有问题。

在“搜索”代码中,我获得了一个密钥列表,其中包含完整路径。我试图直接使用完整路径删除密钥,但这是不可能的,因为RegistryKey必须使用RegistryHive进行初始化(例如RegistryHive.ClassesRoot),但RegistryHive已经完全在路径中。

如何获得删除授权?

2 个答案:

答案 0 :(得分:0)

你有一个完整的例子 Read, write and delete from registry with C#

MSDN Doc

这是一个好的开始,希望它有所帮助!

答案 1 :(得分:0)

默认情况下,在64位Windows操作系统上,32位应用程序访问32位注册表项,而64位应用程序访问64位注册表项。

例如,64位密钥:

HKEY_LOCAL_MACHINE\Software\NVIDIA Corporation

和32位密钥:

HKEY_LOCAL_MACHINE\Software\WOW6432Node\NVIDIA Corporation

没有相同的内容。

因此,如果在64位操作系统上从32位应用程序打开HKEY_LOCAL_MACHINE\Software\NVIDIA Corporation,则将自动重定向到HKEY_LOCAL_MACHINE\Software\WOW6432Node\NVIDIA Corporation,除非您在打开密钥时指定所需的注册表视图。

实际上,这意味着对于HKEY_LOCAL_MACHINE\SoftwareHKEY_CLASSES_ROOT,您必须打开并搜索64位和32位注册表视图。

关于为什么有时看到一个键而有时却不太可能解释为为什么没有在交互式用户上下文中运行该应用程序的原因:

当您从运行在 交互式用户帐户,系统将合并默认设置 HKEY_LOCAL_MACHINE\Software\Classes与互动用户的 HKEY_CURRENT_USER\Software\Classes中的设置。欲获得更多信息 有关如何合并这些设置的信息,请参见Merged View of HKEY_CLASSES_ROOT

有关其他内容,请向full documentation查询HKEY_CLASSES_ROOT密钥。