Revision: 10087
Updated Code
at December 8, 2008 10:36 by jimfred
Updated Code
/// <summary>
/// Given a registry key, get a list of child sub-keys.
/// This function recursively calls itself.
/// Intended to be used in an implementation of recursive enumeration in
/// either a foreach loop or a LINQ expression.
/// If access to a key is not allowed, such subkeys are not included in the list and
/// a Debug.WriteLine prints the key name.
/// <example>
/// string searchString = "dll".ToLower(); // Example search for mention of dll. 'ToLower' is used for non-case-sensisitve search.
/// Microsoft.Win32.RegistryKey keyStart = rkLm.OpenSubKey(@"SOFTWARE\Adobe\");
///
/// // LINQ expression to retrieve a list of strings based on the 'where' condition.
/// IEnumerable<string> regVals2 =
/// // These two 'from' clauses allow nested enumeration of keys and their values.
/// from key in GetSubKeys(keyStart)
/// from valueName in key.GetValueNames()
/// // create a string 'value' for convenient access to value.
/// let value = key.GetValue(valueName).ToString()
/// where
/// // this example where clause searches for searchString.
/// // and of course could be enhanced to narrow search results.
/// // 'ToLower' is used for non-case-sensisitve search.
/// value.ToLower().Contains(searchString) ||
/// valueName.ToLower().Contains(searchString) ||
/// key.Name.ToLower().Contains(searchString)
/// // format a string containing the key name, value name and value.
/// // Hint: call a member function here to allow setting of break points.
/// select string.Format("{0}: {1}={2}", key.Name, valueName.ToString(), value);
/// </example>
/// </summary>
/// <param name="keyParentArg">A registry key</param>
/// <returns>An IEnumerable List of subkeys under the keyParentArg.</returns>
static IEnumerable<Microsoft.Win32.RegistryKey> GetSubKeys(Microsoft.Win32.RegistryKey keyParentArg)
{
// This link... http://www.csharphelp.com/archives2/archive430.html
// ...has a GetSubKeys implementation without try/catch.
// Omitting try/catch will cause LINQ expressions to abort prematurely.
// This link... http://support.microsoft.com/kb/267908 -
// ...has an example that enumerates using advapi32.dll without .NET or LINQ.
// This link... http://blog.domaindotnet.com/2008/09/08/the_fastest_dot_net_hash_set_collection_with_linq_extended_features/
// ...has an alternative implementation (using GetAllSubkeys and TryOpenSubKey) that
// I thought was more complex than necessary for simple registry enumeration. This
// GetSubKeys function provides similar functionality with one function.
// This list will be built as subkeys are added.
List<Microsoft.Win32.RegistryKey> keysFound = new List<Microsoft.Win32.RegistryKey>();
try
{
if (keyParentArg.SubKeyCount > 0)
{
foreach (string strKeyChild in keyParentArg.GetSubKeyNames())
{
try
{
Microsoft.Win32.RegistryKey keyChild = keyParentArg.OpenSubKey(strKeyChild);
if (keyChild != null)
{
keysFound.Add(keyChild);
// Recursive call back into this method
IEnumerable<Microsoft.Win32.RegistryKey> keyGrandChildren = GetSubKeys(keyChild);
if (keyGrandChildren != null)
{
keysFound.AddRange(keyGrandChildren);
}
else
{
System.Diagnostics.Debug.Assert(false);
}
} // if not null.
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message + Environment.NewLine + " failed trying " + strKeyChild + " in " + keyParentArg);
}
} // foreach
} // if
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message + Environment.NewLine + " failed trying " + keyParentArg);
}
return keysFound;
} // GetSubKeys()
Revision: 10086
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at December 7, 2008 16:59 by jimfred
Initial Code
/// <summary>
/// Given a registry key, get a list of child sub-keys.
/// This function recursively calls itself.
/// Intended to be used in an implementation of recursive enumeration in
/// either a foreach loop or a LINQ expression.
/// If access to a key is not allowed, such subkeys are not included in the list and
/// a Debug.WriteLine prints the key name.
/// <example>
/// string searchString = "dll".ToLower(); // Example search for mention of dll.
/// Microsoft.Win32.RegistryKey keyStart = rkLm.OpenSubKey(@"SOFTWARE\Adobe\");
///
/// // LINQ expression to retrieve a list of strings based on the 'where' condition.
/// IEnumerable<string> regVals2 =
/// // These two 'from' clauses allow nested enumeration of keys and their values.
/// from key in GetSubKeys(keyStart)
/// from valueName in key.GetValueNames()
/// // create a string 'value' for convenient access to value.
/// let value = key.GetValue(valueName).ToString()
/// where
/// // this example where clause searches for searchString.
/// // and of course could be enhanced to narrow search results.
/// // 'ToLower' is used for non-case-sensisitve search.
/// value.ToLower().Contains(searchString) ||
/// valueName.ToLower().Contains(searchString) ||
/// key.Name.ToLower().Contains(searchString)
/// // format a string containing the key name, value name and value.
/// // Hint: call a member function here to allow setting of break points.
/// select string.Format("{0}: {1}={2}", key.Name, valueName.ToString(), value);
/// </example>
/// </summary>
/// <param name="keyParentArg">A registry key</param>
/// <returns>An IEnumerable List of subkeys under the keyParentArg.</returns>
static IEnumerable<Microsoft.Win32.RegistryKey> GetSubKeys(Microsoft.Win32.RegistryKey keyParentArg)
{
// This link... http://www.csharphelp.com/archives2/archive430.html
// ...has a GetSubKeys implementation without try/catch.
// Omitting try/catch will cause LINQ expressions to abort prematurely.
// This link... http://support.microsoft.com/kb/267908 -
// ...has an example that enumerates using advapi32.dll without .NET or LINQ.
// This link... http://blog.domaindotnet.com/2008/09/08/the_fastest_dot_net_hash_set_collection_with_linq_extended_features/
// ...has an alternative implementation (using GetAllSubkeys and TryOpenSubKey) that
// I thought was more complex than necessary for simple registry enumeration. This
// GetSubKeys function provides similar functionality with one function.
// This list will be built as subkeys are added.
List<Microsoft.Win32.RegistryKey> keysFound = new List<Microsoft.Win32.RegistryKey>();
try
{
if (keyParentArg.SubKeyCount > 0)
{
foreach (string strKeyChild in keyParentArg.GetSubKeyNames())
{
try
{
Microsoft.Win32.RegistryKey keyChild = keyParentArg.OpenSubKey(strKeyChild);
if (keyChild != null)
{
keysFound.Add(keyChild);
// Recursive call back into this method
IEnumerable<Microsoft.Win32.RegistryKey> keyGrandChildren = GetSubKeys(keyChild);
if (keyGrandChildren != null)
{
keysFound.AddRange(keyGrandChildren);
}
else
{
System.Diagnostics.Debug.Assert(false);
}
} // if not null.
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message + Environment.NewLine + " failed trying " + strKeyChild + " in " + keyParentArg);
}
} // foreach
} // if
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message + Environment.NewLine + " failed trying " + keyParentArg);
}
return keysFound;
} // GetSubKeys()
Initial URL
See URLs in comments in function
Initial Description
This static function allows LINQ or foreach access to registry keys to search for keys, value names and/or values. See example usage in <example>. This was created to find occurrences of driver references ( MyDriver.sys and corresponding OEMnnn.INF) in the registry. LINQ access to the registry provides for fancy conditions in where-clauses. Try/catch blocks are used to handle (ignore) access exceptions.
Initial Title
GetSubKeys - static function provides recursive access to registry keys with LINQ queries or foreach loops
Initial Tags
Initial Language
C#