Find the Executing function's name

Often I want to write the SAME code that will display the name of the currently executing method or function. That way I can just copy/paste the same code into multiple methods.

For example, in sub Form1_Load I could put this line:

        System.Diagnostics.Debug.WriteLine("in Form1_Load")

In Button1_Click I’d have to out a different line:

        System.Diagnostics.Debug.WriteLine("in Button1_Click")

           

In FoxPro, I can use the PROGRAM() function. How do you do it in .Net? Like this:

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        System.Diagnostics.Debug.WriteLine("subroutine name = " + (New StackTrace).GetFrames(0).GetMethod.Name)

    End Sub

The output is:

subroutine name = Form1_Load

I use something similar to this code in my Unit Tests (Use Visual Studio Test framework to create tests for your code) so the test code can detect what the name of the test is.

In fact, you can even find out the calling assembly within a program, and do something different depending on the caller!

In fact, run this code:

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim st = New StackTrace

        Dim Methods = st.GetFrames

        For Each meth In Methods

            System.Diagnostics.Debug.WriteLine(meth.GetMethod.DeclaringType.FullName + ":" + meth.GetMethod.Name)

        Next

    End Sub

 If you set a breakpoint in this code, you’ll see that the output shows the method names:

This is the actual debugger output:

WindowsApplication1.exe!WindowsApplication1.Form1:Form1_Load

mscorlib.dll!System.EventHandler:Invoke

System.Windows.Forms.dll!System.Windows.Forms.Form:OnLoad

System.Windows.Forms.dll!System.Windows.Forms.Form:OnCreateControl

System.Windows.Forms.dll!System.Windows.Forms.Control:CreateControl

System.Windows.Forms.dll!System.Windows.Forms.Control:CreateControl

System.Windows.Forms.dll!System.Windows.Forms.Control:WmShowWindow

System.Windows.Forms.dll!System.Windows.Forms.Control:WndProc

System.Windows.Forms.dll!System.Windows.Forms.ScrollableControl:WndProc

System.Windows.Forms.dll!System.Windows.Forms.ContainerControl:WndProc

System.Windows.Forms.dll!System.Windows.Forms.Form:WmShowWindow

System.Windows.Forms.dll!System.Windows.Forms.Form:WndProc

System.Windows.Forms.dll!System.Windows.Forms.Control+ControlNativeWindow:OnMessage

System.Windows.Forms.dll!System.Windows.Forms.Control+ControlNativeWindow:WndProc

System.Windows.Forms.dll!System.Windows.Forms.NativeWindow:DebuggableCallback

System.Windows.Forms.dll!System.Windows.Forms.SafeNativeMethods:ShowWindow

System.Windows.Forms.dll!System.Windows.Forms.Control:SetVisibleCore

System.Windows.Forms.dll!System.Windows.Forms.Form:SetVisibleCore

System.Windows.Forms.dll!System.Windows.Forms.Control:set_Visible

System.Windows.Forms.dll!System.Windows.Forms.Application+ThreadContext:RunMessageLoopInner

System.Windows.Forms.dll!System.Windows.Forms.Application+ThreadContext:RunMessageLoop

System.Windows.Forms.dll!System.Windows.Forms.Application:Run

Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase:OnRun

Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase:DoApplicationModel

Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase:Run

WindowsApplication1.exe!WindowsApplication1.My.MyApplication:Main

mscorlib.dll!System.AppDomain:_nExecuteAssembly

mscorlib.dll!System.AppDomain:ExecuteAssembly

Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc:RunUsersAssembly

mscorlib.dll!System.Threading.ThreadHelper:ThreadStart_Context

mscorlib.dll!System.Threading.ExecutionContext:Run

mscorlib.dll!System.Threading.ThreadHelper:ThreadStart

This is the actual stack from the Call Stack window (turn off Tools->Options->Debugging->Just My Code):

> WindowsApplication1.exe!WindowsApplication1.Form1.Form1_Load(Object sender = {WindowsApplication1.Form1}, System.EventArgs e = {System.EventArgs}) Line 9 Basic

  [Native to Managed Transition]

  [Managed to Native Transition]

  System.Windows.Forms.dll!System.Windows.Forms.Form.OnLoad(System.EventArgs e) + 0x28b bytes

  System.Windows.Forms.dll!System.Windows.Forms.Form.OnCreateControl() + 0x52 bytes

  System.Windows.Forms.dll!System.Windows.Forms.Control.CreateControl(bool fIgnoreVisible) + 0x172 bytes

  System.Windows.Forms.dll!System.Windows.Forms.Control.CreateControl() + 0x1b bytes

  System.Windows.Forms.dll!System.Windows.Forms.Control.WmShowWindow(ref System.Windows.Forms.Message m) + 0x8e bytes

  System.Windows.Forms.dll!System.Windows.Forms.Control.WndProc(ref System.Windows.Forms.Message m) + 0x6ed bytes

  System.Windows.Forms.dll!System.Windows.Forms.ScrollableControl.WndProc(ref System.Windows.Forms.Message m) + 0x45 bytes

  System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.WndProc(ref System.Windows.Forms.Message m) + 0x11 bytes

  System.Windows.Forms.dll!System.Windows.Forms.Form.WmShowWindow(ref System.Windows.Forms.Message m) + 0x3e bytes

  System.Windows.Forms.dll!System.Windows.Forms.Form.WndProc(ref System.Windows.Forms.Message m) + 0x230 bytes

  System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.OnMessage(ref System.Windows.Forms.Message m) + 0xd bytes

  System.Windows.Forms.dll!System.Windows.Forms.Control.ControlNativeWindow.WndProc(ref System.Windows.Forms.Message m) + 0x36 bytes

  System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DebuggableCallback(System.IntPtr hWnd, int msg = 24, System.IntPtr wparam, System.IntPtr lparam) + 0x57 bytes

  [Native to Managed Transition]

  [Managed to Native Transition]

  System.Windows.Forms.dll!System.Windows.Forms.Control.SetVisibleCore(bool value = true) + 0x12f bytes

  System.Windows.Forms.dll!System.Windows.Forms.Form.SetVisibleCore(bool value = true) + 0xdc bytes

  System.Windows.Forms.dll!System.Windows.Forms.Control.Visible.set(bool value) + 0xe bytes

  System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(int reason = -1, System.Windows.Forms.ApplicationContext context = {Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.WinFormsAppContext}) + 0xee bytes

  System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x53 bytes

  System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System.Windows.Forms.ApplicationContext context) + 0x15 bytes

  Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun() + 0xc0 bytes

  Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel() + 0xe4 bytes

  Microsoft.VisualBasic.dll!Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(string[] commandLine) + 0x62 bytes

  [Native to Managed Transition]

  [Managed to Native Transition]

  mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) + 0x39 bytes

  Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() + 0x2b bytes

  mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x3b bytes

  mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x81 bytes

  mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x40 bytes

You can get similar results from Foxpro. Program(-1) will return the # of stack frames. SYS(16) returns the executing program, and Program(i) returns the name of the procedure at the stack level i.

res=func1()

?res

PROCEDURE func1

          ?PROGRAM()

          RETURN func2()

PROCEDURE func2

          ?PROGRAM()

          ?PROGRAM(-1)

          FOR i = 1 TO PROGRAM(-1)

                   ?SYS(16)+ PROGRAM(i)

          ENDFOR

         

          RETURN 4

See also How to log application API calls using import module addresses