Search code examples
c#dnlib

Read assembly MethodBody, parse its Name in a ListBox and its IL in a TextBox?


I have a WPF MainWindow Form with a ListBox and a TextBox that looks like this:

Figure A. WPF MainWindow with Sample Text. Figure A. WPF MainWindow with Sample Text.

Now, the Load Assembly... OnClick button event allows me to select a .NET Assembly and load it up using DnLib

Then, if I want to display the Methods bodies I would do it like so:

Assembly asm = Assembly.LoadFile(filename);
                foreach (Module mod in asm.GetModules())
                {
                    foreach (Type types in mod.GetTypes())
                    {
                        foreach (MethodInfo mdInfo in types.GetMethods())
                        {
                            listBox.Items.Add(mdInfo.Name);
                        }
                    }
                }

This adds each found Method name to the ListBox on the left, resulting like so:

Figure B. Showing the ListBox Filled with Methods Names Figure B. Showing the ListBox Filled with Methods Names

Now the trick part, I would like to for whichever method I select from the ListBox to display its respective MethodBody IL on the TextBox

How can I achieve such thing?


Solution

  • «Phew!» Finally Solved it!

    Here's the solution for whoever tries to do the same thing in the future.

    Make an instance of 'List' and then iterate through the methods and assign the names to such list, then whenever your SelectedItem index value changes, I can simply call GetMethodBodyByName and then I can surely solve this issue

    Here's how to implement the function GetMethodBodyByName:

    public string GetMethodBodyByName(string methodName)
        {
            ModuleDefMD md = ModuleDefMD.Load(filename);
            foreach (TypeDef type in md.Types)
            {
                foreach (MethodDef method in type.Methods)
                {
                    for (int i = 0; i < type.Methods.Count; i++)
                    {
                        if (method.HasBody)
                        {
                            if (method.Name == methodName)
                            {
                                var instr = method.Body.Instructions;
                                return String.Join("\r\n", instr);
                            }
                        }
                    }
                }
            }
            return "";
        }
    

    The idea is that 'GetMethodBodyByName' will receive the method name as a parameter, then it will iterate through methods and see if a method matches the given name, then if found, the function will just simply iterate through that method and output the method's body.

    Here's how my ListBox_SelectedItemChanged event looks like:

    private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            textBox.Text = "";
            textBox.Text = GetMethodBodyByName(method[listBox.SelectedIndex].Name);
        }
    

    That's All Folks!

    Note: Be careful when doing this approach as if when you request names, different methods can have the same names. But that's a cake for another day, I'm done for now! take care bye-bye!


    Working our way up for the Ultimate Solution!

    The WPF MainWindow Forms carry with themselves two little useful properties, they are: Tag and Content, the idea is the following one:

    With the Tag and Content Property we can assign any values to it that later it can be retrieved On-The-Fly without having to depend on Methods names specifically for this task.

    So you would instead of looping each method and get its name respectively you can just do the way I did:

    Iterate through the Method, and assign its body to the Tag property, and its name to the Content property, as this last property is the one that handles the actual Title property, so disregarding anything you do with the method in the future and even if it had the same name of another one, it will work no matter what.

    How Can We Implement It?

    Simply:

    <...>
    // Inside Method Body iteration routine...
    <...>
    
    var instr = mdInfo.Body.Instructions;
    
                            // Allocate in a new `ListBoxItem` each method and add it to the current listbox with their
                            // ... respective Tag and Content information... // Many Thanks Kao :D
                            newItem = new ListBoxItem();
                            newItem.Content = mdInfo.Name;
                            newItem.Tag = string.Join("\r\n", instr);
    
                            method.Add(mdInfo);
                            listBox.Items.Add(newItem);
    

    Then on your SelectedItem Index-Value-Changed Event put this:

                MSILTextBox.Clear();
                // Retrieve them given the selected index...
                // ... the returned value will be the Tag content of the ...
                // ... previously saved item.
                string getTag= ((ListBoxItem)listBox.SelectedItem).Tag.ToString();
                MSILTextBox.Text = getTag;