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#