How to get CallerFilePath and CallerLineNumber without using CallerInfo attributes?

For my log4net solution, I have an API wrapper that uses CallerInfo attributes like

    public void Write(string message,
                            [CallerMemberName] string memberName = "",
                            [CallerFilePath] string filePath = "",
                            [CallerLineNumber] int lineNumber = 0)

      

However, I also use Unity Interception so that I can trace the protocols before / after responses, eg. using ICallHandler as shown below in the Invoke method.

public class TraceCallHandler : ICallHandler
{
...

   public IMethodReturn Invoke(IMethodInvocation input, 
                               GetNextHandlerDelegate getNext)
    {
        //---- Trace method inputs
        this.LogInfoBeforeInvoke(input);

        //---- invoking the target method
        InvokeHandlerDelegate next = getNext();
        IMethodReturn methodReturn = next(input, getNext);

        //---- invoking the target method
        this.LogInfoAfterInvoke(methodReturn.ReturnValue); 
    }
}

      

Note. The above code is not complete / correct ... but just wanted to show you what I was doing for Unity Interception.

My question / challenge: When I end up calling log.Write (...), I want the caller information of the target, not my TraceCallHandler information.

eg. for the method name I can do this:

   string methodName = input.MethodBase.Name;

      

How to get the caller file path and caller number? Can this be done even through reflection?

Thank!

+3


source to share


2 answers


Yes, you can get them with reflection:

var sf = new System.Diagnostics.StackTrace(1).GetFrame(0);
Console.WriteLine(" File: {0}", sf.GetFileName());
Console.WriteLine(" Line Number: {0}", sf.GetFileLineNumber());
// Note that the column number defaults to zero 
// when not initialized.
Console.WriteLine(" Column Number: {0}", sf.GetFileColumnNumber());

      

However, as he clearly says in the documentation :



The StackFrame information will be most informative with the Debug configuration build. By default, Debug builds include debug symbols, while Release builds do not. Debug symbols contain most of the file, method name, line number, and column data used when building StackFrame objects.

So, if all you want is debug then enable it in debug builds and open. In release builds, although it will be useless at best and, at worst, just misleading because apart from the symbol considerations above, the compiler will aggressively inject methods and reorder things and generally mess with your things.

+5


source


I just ran into this problem and thought I'd share what I learned. First, when you include [CallerFilePath] in a method argument, the side effect is that the full path to the file, including any user-identifiable data, will be included in your .exe. I created a simple program in one way. I created an exe. Then I added the [CallerFilePath] attribute to the test function. When I compared the results of strings.exe (from sysinternals), the one with the attribute was different in that it included the full path to the source file.

c:\users\<my name>\documents\visual studio 2015\Projects\TestCallerAttribute\TestCallerAttribute\Program.cs

      

The answer above by stuartd is correct in that you will not be able to get the data you want from the stack trace in a release build.



However, there is a solution to get strong data: Event Tracing for Windows. From msdn: "Event Tracing for Windows (ETW) is an efficient kernel-level tracking tool that allows you to log kernel or application events to a log file. You can use events in real time or from a log file and use them to debug your application or determine if what performance problems are there in the application. "

This is not a quick fix. There is work to set up events and listeners to get the origin you want. The long-term payoff is strong.

+1


source







All Articles