سؤال

I'm a bit frustrating trying to figure out what the best route is to handle exceptions in C# with a try-catch statement. I want to have the code so if an exception is thrown trying to open a Registry key then it will move on to the next Registry key. The only way I can think of to do is this by encapsulating each of the function calls in a try-catch statement but to me it seems long way to do that.

  • Is there any other way to do this?
  • Can you have all the code in a single try-catch statement and when an exception occurs, have it move to the next line of code (like step over)?
  • I know this is probably a no, but can the ScanSubKey function be used to check for exceptions if the variable is set in a parameter?

Without try-catch statements

ScanSubKey(Registry.ClassesRoot);
ScanSubKey(Registry.LocalMachine.OpenSubKey("SOFTWARE"));
ScanSubKey(Registry.CurrentUser.OpenSubKey("SOFTWARE"));
if (Is64BitOS)
{
    ScanSubKey(Registry.ClassesRoot.OpenSubKey("Wow6432Node"));
    ScanSubKey(Registry.LocalMachine.OpenSubKey("SOFTWARE\\Wow6432Node"));
    ScanSubKey(Registry.CurrentUser.OpenSubKey("SOFTWARE\\Wow6432Node"));
}

Example

try {
    ScanSubKey(Registry.ClassesRoot);
} 
catch (Exception ex) {
    Debug.WriteLine("The following error occurred opening a registry key: " + ex.Message);
}
try {
    ScanSubKey(Registry.LocalMachine.OpenSubKey("SOFTWARE"));
} 
catch (Exception ex) {
    Debug.WriteLine("The following error occurred opening a registry key: " + ex.Message);
}
try {
    ScanSubKey(Registry.CurrentUser.OpenSubKey("SOFTWARE"));
} 
catch (Exception ex) {
    Debug.WriteLine("The following error occurred opening a registry key: " + ex.Message);
}

if (Is64BitOS)
{
    try {
        ScanSubKey(Registry.ClassesRoot.OpenSubKey("Wow6432Node"));
    } 
    catch (Exception ex) {
        Debug.WriteLine("The following error occurred opening a registry key: " + ex.Message);
    }
    try {
        ScanSubKey(Registry.LocalMachine.OpenSubKey("SOFTWARE\\Wow6432Node"));
    } 
    catch (Exception ex) {
        Debug.WriteLine("The following error occurred opening a registry key: " + ex.Message);
    }
    try {
        ScanSubKey(Registry.CurrentUser.OpenSubKey("SOFTWARE\\Wow6432Node"));
    } 
    catch (Exception ex) {
        Debug.WriteLine("The following error occurred opening a registry key: " + ex.Message);
    }
}
هل كانت مفيدة؟

المحلول 3

I call this an "Executor":

    public static void Execute(Action action)
    {
        try
        {
            action();
        }
        catch (Exception ex)
        {
        }
    }

and then use it:

Execute(() => ScanSubKey(Registry.ClassesRoot));

نصائح أخرى

Create a new method TryScanSubKey. Then your code looks clean again:

TryScanSubKey(Registry.ClassesRoot);
TryScanSubKey(Registry.LocalMachine.OpenSubKey("SOFTWARE"));
TryScanSubKey(Registry.CurrentUser.OpenSubKey("SOFTWARE"));
if (Is64BitOS)
{
    TryScanSubKey(Registry.ClassesRoot.OpenSubKey("Wow6432Node"));
    TryScanSubKey(Registry.LocalMachine.OpenSubKey("SOFTWARE\\Wow6432Node"));
    TryScanSubKey(Registry.CurrentUser.OpenSubKey("SOFTWARE\\Wow6432Node"));
}

The implementation of TryScanSubKey should be obvious, but, for completeness, here it is:

void TryScanSubKey(RegistryKey key)
{
    try
    {
        ScanSubKey(key);
    } 
    catch (Exception ex)
    {
        Debug.WriteLine("The following error occurred opening a registry key: " + ex.Message);
    }
}

Note that, in general, swallowing an error is bad practice, and swallowing all errors is worse still. So please consider (at least) replacing catch (Exception ex) with something more specific, e.g. catch (TheSpecificExceptionThrownByScanSubKey ex).

Maybe this would be a slightly better approach:

public bool TryOpenRegKey(RegistryKey regKey, string subKey = default(string))
{
  try
  {
    if (string.IsNullOrWhiteSpace(subKey))
      ScanSubKey(regKey);
    else
      ScanSubKey(regKey.OpenSubKey(subKey));

    return true;
  }
  catch(Exception ex)
  {
    Debug.WriteLine("The following error occurred opening a registry key: " + ex.Message);
    return false;
  }
}

Then:

TryOpenRegKey(Registry.ClassesRoot);
TryOpenRegKey(Registry.LocalMachine, "SOFTWARE");
TryOpenRegKey(Registry.CurrentUser, "SOFTWARE");

if (Is64BitOS)
{
  TryOpenRegKey(Registry.ClassesRoot, "Wow6432Node");
  TryOpenRegKey(Registry.LocalMachine, "SOFTWARE\\Wow6432Node");
  TryOpenRegKey(Registry.CurrentUser, "SOFTWARE\\Wow6432Node");
}

Have you considered placing a try/catch inside of the ScanSubKey function itself and return if an error occurs?

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top