WillingMost7 Ответов: 2

C# catch исключение игнорируется, таким образом приложение давит


Мне нужно сделать приложение в WinForm C# в качестве моего окончательного проекта программирования. Проект заключается в том, чтобы более красиво управлять реестром, чтобы облегчить пользователю редактирование значений.
Проблема в том, что когда я читаю, существует ли UninstallString или нет, функция по какой-то причине не заглядывает в catch внутри try, когда она терпит неудачу (и она терпит неудачу, так как приложение не является 64-разрядным, поэтому к значению реестра нужно обращаться по-другому)

public bool ValueExists(string Key, string Value)
    {
        try
        {
            try
            {
                RegistryKey rk = Registry.LocalMachine.OpenSubKey(Key);
                return rk.GetValue(Value) != null; //Error happens here when selected 64-bit application. System.NullReferenceException: 'Object reference not set to an instance of an object.'
            }
            catch (NullReferenceException ex)
            {
                RegistryKey regkey64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
                RegistryKey rk64 = regkey64.OpenSubKey(Value);
                return regkey64.OpenSubKey(Key).GetValue(Value) != null;
            }
        }
        catch
        {
            return false;
        }
    }


System.NullReferenceException: 'ссылка на объект не установлена на экземпляр объекта.' - это ошибка, и я знаю, что это происходит, потому что я выбираю 64-разрядное приложение, но по какой-то причине оно игнорирует улов.

Что я уже пробовал:

try
            {
                RegistryKey regkey64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
                RegistryKey rk64 = regkey64.OpenSubKey(Value);
                return regkey64.OpenSubKey(Key).GetValue(Value) != null;
            }
            catch (NullReferenceException ex)
            {
                RegistryKey rk = Registry.LocalMachine.OpenSubKey(Key);
                return rk.GetValue(Value) != null;
            }


Если я поменяю порядок так, что при выборе 64-битного значения реестра он не рухнет, но при выборе 32-битного значения реестра он рухнет с той же ошибкой.
rk имеет значение null при правильных обстоятельствах - что означает, что выбранное 32-разрядное значение реестра не существует. Но опять же, если выбранное значение реестра 64-битное, оно будет нечитаемым, поэтому мне нужно использовать код в попытке внутри улова (чтобы проверить, существует ли 64-битное значение реестра или нет).

2 Ответов

Рейтинг:
17

Richard Deeming

Вы потенциально бросаете еще один NullReferenceException из вашего первого catch блок.

Но вам не нужен ни один из этих блоков улова:

public bool ValueExists(string Key, string Value)
{
    using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(Key, false))
    {
        if (rk != null) return rk.GetValue(Value) != null;
    }
    
    if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
    {
        using (RegistryKey hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
        using (RegistryKey rk = hklm.OpenSubKey(Value, false))
        {
            if (rk != null) return rk.GetValue(Value) != null;
        }
    }
    
    return false;
}


WillingMost7

Спасибо вам оооооооооочень много!!! Это действительно сработало.
Хотя мне пришлось внести изменения во второй, если вы написали (потому что была ошибка, она показывала неправильный вывод).

Я сохранил второе Если но заменил все внутри этим:
Объект registrykey regkey64 = объект registrykey.OpenBaseKey(RegistryHive.Значение LocalMachine, RegistryView.Registry64);
верните regkey64.OpenSubKey(ключ).GetValue(значение) != null;

Рейтинг:
1

Richard MacCutchan

Почему вы рассчитываете на NullReferenceException чтобы проверить правильность кода. Вы должны проверить возвращаемое значение из любого вызова реестра, чтобы увидеть, является ли оно нулевым, прежде чем продолжить. Вы никогда не должны писать такой код, как:

RegistryKey rk = Registry.LocalMachine.OpenSubKey(Key);
return rk.GetValue(Value) != null;

Так как возвращаемое значение из OpenSubKey может быть null.


WillingMost7

Если искомое значение существует то оно не равно нулю

Richard MacCutchan

Ну, это довольно очевидно.

WillingMost7

Хорошо, а как еще вы предлагаете это написать?

Richard MacCutchan

Я уже предлагал это: всегда проверяйте возвращаемые значения из системных вызовов, чтобы увидеть, являются ли они нулевыми.