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

本文关键字:删除 注册表 查找 | 更新日期: 2023-09-27 18:29:34

我正在寻找一个可以找到注册表项并将其删除的脚本。我的密钥是:"{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:无法写入注册表项。

当我尝试在管理模式下启动应用程序时,我也遇到了同样的错误。但是当我尝试手动从regedit中删除密钥时,没有问题。

在"搜索"代码中,我得到了一个带有完整路径的键列表。我曾尝试使用完整路径直接删除密钥,但这是不可能的,因为必须使用RegistryHive(例如RegistryHive.ClassesRoot)初始化RegistryKey,但RegistryHive在完整路径中已准备就绪。

如何获得删除授权?

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

您有一个完整的示例使用C#从注册表中读取、写入和删除

和MSDN Doc

这是一个良好的开端,希望能有所帮助!

默认情况下,在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与交互式用户CCD_ 6的设置。有关详细信息有关如何合并这些设置,请参见的合并视图HKEY_CLASSES_ROOT。

有关其他内容,请参阅HKEY_CLASSES_ROOT键的完整文档。