Sotelo
Sotelo

Reputation: 287

C# program that dumps the entire HKLM registry tree to the console?

I'm trying to write a simple console app that dumps the contents of HKLM to the console. The output should look something like:

HKEY_LOCAL_MACHINE  
HKEY_LOCAL_MACHINE\BCD00000000
  HKEY_LOCAL_MACHINE\BCD00000000\Description
    KeyName: BCD00000000
    System: 1
    TreatAsSystem: 1
    GuidCache: System.Byte[]
  HKEY_LOCAL_MACHINE\BCD00000000\Objects
    HKEY_LOCAL_MACHINE\BCD00000000\Objects\{0ce4991b-e6b3-4b16-b23c-5e0d9250e5d9}
      HKEY_LOCAL_MACHINE\BCD00000000\Objects\{0ce4991b-e6b3-4b16-b23c-5e0d9250e5d9}\Description
        Type: 537919488
      HKEY_LOCAL_MACHINE\BCD00000000\Objects\{0ce4991b-e6b3-4b16-b23c-5e0d9250e5d9}\Elements
        HKEY_LOCAL_MACHINE\BCD00000000\Objects\{0ce4991b-e6b3-4b16-b23c-5e0d9250e5d9}\Elements\16000020
          Element: System.Byte[]

I haven't had much luck researching how to do this. Any help would be greatly appreciated.

Upvotes: 1

Views: 3097

Answers (4)

cheerless bog
cheerless bog

Reputation: 934

using System;
using System.Text;
using Microsoft.Win32;

class Program
{
    static void Main(string[] args)
    {
        using RegistryKey key = Registry.LocalMachine;
        string keyName = args[0]; // eg @"SOFTWARE\Microsoft\Speech\Voices"

        var sb = new StringBuilder();
        var subKey = key.OpenSubKey(keyName);
        Traverse(subKey);

        void Traverse(RegistryKey key, int indent = 0)
        {
            sb.AppendLine(new string(' ', Math.Max(0, indent - 2)) + key.Name);

            indent++;
            string[] valnames = key.GetValueNames();
            foreach (string valname in valnames)
            {
                sb.AppendLine(new string(' ', indent) + valname + " : " + key.GetValue(valname));
            }

            string[] names = key.GetSubKeyNames();

            foreach (var subkeyname in names)
            {
                Traverse(key.OpenSubKey(subkeyname), indent + 2);
            }
        }

        Console.WriteLine(sb.ToString());
    }
}

Upvotes: 0

Sotelo
Sotelo

Reputation: 287

thanks for the answer Pierre-Alain Vigeant, i like ur solution. for the most part it worked with a couple of minor alterations for the text formatting, but i still couldnt deal with the security exception that was being thrown. turns out linq is not so great for this because it does alot of behind the scenes stuff. the following solution is a basic idea of how to do it

class Program
{
    static void Main(string[] args)
    {
        RegistryKey key = Registry.LocalMachine;

        Traverse(key, 0);

        key.Close();
        Console.Read();

    }

    private static void Traverse(RegistryKey key, int indent)
    {
        Console.WriteLine(key.Name);
        string[] names = key.GetSubKeyNames();


        foreach (var subkeyname in names)
        {

            try
            {
                string[] valnames = key.GetValueNames();
                foreach (string valname in valnames)
                {
                    Console.WriteLine(returnIndentions(indent)+valname + ":" + key.GetValue(valname));

                }
                Traverse(key.OpenSubKey(subkeyname),indent++);
            }
            catch { 
            //do nothing
            }
        }
    }

    private static string returnIndentions(int indent)
    {
        string indentions = "";
        for (int i = 0; i < indent; i++) {
            indentions += " ";
        }
        return indentions;
    }

}

Upvotes: 1

Pierre-Alain Vigeant
Pierre-Alain Vigeant

Reputation: 23103

cHao way is the safiest approach to your question. In the meanwhile, I was bored on this sunday night and wrote something. Just change the Console.WriteLine or add a few other Console.WriteLine to suit your need, whatever need there is.

class Program
{
    static void Main(string[] args)
    {
        Registry.CurrentUser.GetSubKeyNames()
            .Select(x => Registry.CurrentUser.OpenSubKey(x))
            .Traverse(key =>
            {
                if (key != null)
                {
                    // You will most likely hit some security exception
                    return key.GetSubKeyNames().Select(subKey => key.OpenSubKey(subKey));
                }

                return null;
            })
            .ForEach(key =>
            {
                key.GetValueNames()
                    .ForEach(valueName => Console.WriteLine("{0}\\{1}:{2} ({3})", key, valueName, key.GetValue(valueName), key.GetValueKind(valueName)));
            });

        Console.ReadLine();
    }
}

public static class Extensions
{
    public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> fnRecurse)
    {
        foreach (T item in source)
        {
            yield return item;

            IEnumerable<T> seqRecurse = fnRecurse(item);

            if (seqRecurse != null)
            {
                foreach (T itemRecurse in Traverse(seqRecurse, fnRecurse))
                {
                    yield return itemRecurse;
                }
            }
        }
    }

    public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
    {
        foreach (var item in source)
        {
            action(item);
        }
    }
}

Upvotes: 2

cHao
cHao

Reputation: 86565

You know there's already an app that dumps registry contents, right?

REG EXPORT HKLM hklm.reg

Fun part is, it exports the keys in a text format, but that text file can be imported using either REG or the registry editor.

Upvotes: 2

Related Questions