Search code examples
.netvb.netwinformsreflectiondnlib

How to use dnlib library to get the instructions of all the methods?


I'm trying to use the dnlib library wich is part of the de4dot project to load an assembly and get the IL instructions contained on the "body" of all the methods.

I've compiled an assmebly with this VB.NET source:

Public Class Main

    Public Sub testmethod(ByVal testparameter As String)
        MsgBox(testparameter)
    End Sub

    Public Class Test2

        Public Function testfunction(ByVal testparameter As String) As String
            Return testparameter
        End Function

    End Class

End Class

I know that the compiler modifies a lot of things, but I think that the method names (in this case) will not be modified, please correct me if I'm wrong.

Then I'm trying to retrieve those methods with this code:

Imports dnlib.DotNet
Imports dnlib.DotNet.Emit

Private Sub Test_Handler() Handles MyBase.Shown

    Dim asmResolver As New AssemblyResolver()
    Dim modCtx As New ModuleContext(asmResolver)

    ' All resolved assemblies will also get this same modCtx
    asmResolver.DefaultModuleContext = modCtx

    ' Enable the TypeDef cache for all assemblies that are loaded
    ' by the assembly resolver. Only enable it if all auto-loaded
    ' assemblies are read-only.
    asmResolver.EnableTypeDefCache = True

    Dim Assembly As ModuleDefMD = ModuleDefMD.Load("C:\WindowsApplication.exe")
    Assembly.Context = modCtx
    ' Use the previously created (and shared) context
    Assembly.Context.AssemblyResolver.AddToCache(Assembly)

    Dim Members As IEnumerable(Of MemberRef) = Assembly.GetMemberRefs

    For Each m As MemberRef In Members

        If m.IsMethodRef Then

            Dim Method As MethodDef = m.ResolveMethod

            If Method.HasBody Then

                Dim sb As New System.Text.StringBuilder
                With sb
                    .AppendLine(String.Format("Method Name: {0}", Method.FullName))
                    .AppendLine()
                    .AppendLine(String.Format("Method Signature: {0}", Method.Signature.ToString))
                    .AppendLine()
                    .AppendLine(String.Format("Method Instructions: {0}", Environment.NewLine &
                                              String.Join(Environment.NewLine, Method.Body.Instructions)))
                End With
                MessageBox.Show(sb.ToString)

            End If

        End If

    Next

End Sub

The problem is that the only documentation of this library that I've seen is the XML documentation file and some very basic examples on the dnlib site that helped me to write the code above, but I'm not sure how to resolve/retrieve those methods 'cause I'm not doinf it properly, the code above does not resolve any method that I've compiled (testmethod and testfunction), instead that it shows me a lot of constructors (.ctor) and other methods.

What I would like to do is just perform an iteration of all the methods (privated, public, etc) contained in the source that I've compiled regardless of the numer of Classes that the project has and regardless of what class contains an specific method, to get its instructions.


Solution

  • It appears you are simply poking around in the Assembly, so all you get back is the stuff defined in AssemblyInfo.vb. What you probably want to do is iterate the Types in the Assembly then drill into the members or properties defined for the one you are looking for.

    This code should get you pointed in the right direction:

    Dim modDef As ModuleDefMD = ModuleDefMD.Load("C:\Temp\ConsoleApplication1.exe")
    
    For Each t As TypeDef In modDef.GetTypes
        'print the Type name
        Console.WriteLine(t.Name)
    
        ' stupid way to match a Type, but will work for demo purposes
        If t.FullName.StartsWith("ConsoleApplication1.Module1") Then
    
            For Each meth As MethodDef In t.Methods
                ' print the method name
                Console.WriteLine("     Method: {0}", meth.Name)
            Next
    
        End If
    Next
    

    The output looks like this, note that your methods are listed.

    <Module>
    MyApplication
    MyComputer
    MyProject
    MyWebServices
    ThreadSafeObjectProvider`1
    InternalXmlHelper
    RemoveNamespaceAttributesClosure
    Module1
         Method: Main
         Method: testmethod
    Test2
         Method: .ctor
         Method: testfunction
    Resources
    MySettings
    MySettingsProperty