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

3

我正在寻找一个能够查找注册表键并删除它的脚本。 我的键类似于:“{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中删除该键时,就没有问题了。

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

如何获取授权以进行删除?

2个回答

0

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中的设置合并。有关如何合并这些设置的更多信息,请参阅HKEY_CLASSES_ROOT的合并视图

如需其他信息,请参阅 HKEY_CLASSES_ROOT 键的完整文档


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接