J - C Sharper J - C Sharper - 2 months ago 8
ASP.NET (C#) Question

How to get the current project name in C# code?

I want to send an email to myself when an exception is thrown. Using StackFrame object, I am able to get File Name, Class Name and even class method that throw the Exception, but I also need to know the project name as many of my ASP.NET project has the same file name, class name and method.

This is my code:

public static string JndGetEmailTextForDebuggingExceptionError(this Exception Ex)
{
StackFrame sf = Ex.JndGetStackFrame();

string OutputHTML = "<i><b><u>For Developer Use Only: </u></b></i>" + "<br>" +
"<br>" +
"Project Name: " + HttpContext.Current.ApplicationInstance.GetType().Assembly.GetName().Name + "<br>" + //Under discussion
"File Name: " + sf.GetFileName() + "<br>" +
"Class Name: " + sf.GetMethod().DeclaringType + "<br>" +
"Method Name: " + sf.GetMethod() + "<br>" +
"Line Number: " + sf.GetFileLineNumber() + "<br>" +
"Line Column: " + sf.GetFileColumnNumber() + "<br>" +
"Error Message: " + Ex.Message + "<br>" +
"Inner Message : " + Ex.InnerException.Message + "<br>";

return OutputHTML;
}


Thanks ALL.

Answer

You can use Assembly.GetCallingAssembly if you have your logging code in a separate library assembly, and call directly from your ASP.NET assembly to your library, and you mark the method so that it won't be inlined:

[MethodImpl(MethodImplOptions.NoInlining)]
public static string JndGetEmailTextForDebuggingExceptionError(this Exception Ex)
{
    StackFrame sf = Ex.JndGetStackFrame();

    string OutputHTML =         "<i><b><u>For Developer Use Only: </u></b></i>"                    + "<br>" + 
                                                                                                     "<br>" +
                                "Project Name:   "  + Assembly.GetCallingAssembly().GetName().Name + "<br>" +
                                "File Name:      "  + sf.GetFileName()                             + "<br>" +
                                "Class Name:     "  + sf.GetMethod().DeclaringType                 + "<br>" +
                                "Method Name:    "  + sf.GetMethod()                               + "<br>" +
                                "Line Number:    "  + sf.GetFileLineNumber()                       + "<br>" +
                                "Line Column:    "  + sf.GetFileColumnNumber()                     + "<br>" +
                                "Error Message:  "  + Ex.Message                                   + "<br>" +
                                "Inner Message : "  + Ex.InnerException.Message                    + "<br>";

    return OutputHTML;
}

On any entry points in your library that can end up wanting to log the project name, you'd have to record the calling assembly and mark it NoInlining, then pass that around internally.

If you're using .NET 4.5, there's an alternative way to do this: CallerFilePath. It has the same restrictions on entry points, and it returns the source path on your machine instead of the assembly name (which is probably less useful), but it's easier to know that it'll work (because it compiles it, just like optional parameters are compiled in), and it allows inlining:

public static string JndGetEmailTextForDebuggingExceptionError
              (this Exception Ex, [CallerFilePath] string filePath = "")
{
    StackFrame sf = Ex.JndGetStackFrame();

    string OutputHTML =         "<i><b><u>For Developer Use Only: </u></b></i>" + "<br><br>" +
                                "Source File Path:   "  + filePath + "<br>" +
...