public static IEnumerable <RegistryObject> WalkHive(RegistryHive Hive, string startingKey = null) { Stack <RegistryKey> keys = new Stack <RegistryKey>(); RegistryKey x86_View = null, x64_View = null; try { x86_View = RegistryKey.OpenBaseKey(Hive, RegistryView.Registry32); } catch (Exception e) when( e is IOException || e is ArgumentException || e is UnauthorizedAccessException || e is System.Security.SecurityException) { } try { x64_View = RegistryKey.OpenBaseKey(Hive, RegistryView.Registry32); } catch (Exception e) when( e is IOException || e is ArgumentException || e is UnauthorizedAccessException || e is System.Security.SecurityException) { } if (x86_View != null) { if (startingKey != null) { x86_View = x86_View.OpenSubKey(startingKey); } keys.Push(x86_View); } if (x64_View != null) { if (startingKey != null) { x64_View = x64_View.OpenSubKey(startingKey); } keys.Push(x64_View); } while (keys.Count > 0) { RegistryKey currentKey = keys.Pop(); if (currentKey == null) { continue; } if (Filter.IsFiltered(AsaHelpers.GetPlatformString(), "Scan", "Registry", "Key", currentKey.Name)) { continue; } // First push all the new subkeys onto our stack. foreach (string key in currentKey.GetSubKeyNames()) { try { var next = currentKey.OpenSubKey(name: key, writable: false); keys.Push(next); } // These are expected as we are running as administrator, not System. catch (System.Security.SecurityException e) { Log.Verbose(e, "Permission Denied: {0}", currentKey.Name); } // There seem to be some keys which are listed as existing by the APIs but don't actually exist. // Unclear if these are just super transient keys or what the other cause might be. // Since this isn't user actionable, also just supress these to the verbose stream. catch (System.IO.IOException e) { Log.Verbose(e, "Error Reading: {0}", currentKey.Name); } catch (Exception e) { Log.Information(e, "Unexpected error when parsing {0}:", currentKey.Name); AsaTelemetry.TrackTrace(Microsoft.ApplicationInsights.DataContracts.SeverityLevel.Error, e); } } var regObj = RegistryKeyToRegistryObject(currentKey); if (regObj != null) { yield return(regObj); } } x86_View.Dispose(); x64_View.Dispose(); }