如何在C#代码中获取当前项目名称?

39
我想在异常抛出时向自己发送电子邮件。使用StackFrame对象,我能够获取文件名、类名甚至是抛出异常的类方法,但我还需要知道项目名称,因为我的许多ASP.NET项目具有相同的文件名、类名和方法。
这是我的代码:
    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;
    }

感谢大家。


听起来有点混乱。为什么不同的项目中文件名和类名要相同呢? - Tim S.
1
@TimS. - 文件名: HomeController.cs; 类名: HomeController; 方法名: Index。这是大多数VS用户在新的MVC项目中使用的模板。 - ken
不确定您所说的“project”是什么意思,是调用汇编语言吗?除非您使用throw(ex)将其销毁,否则应该在堆栈跟踪中。使用某种应用程序记录器并附加输出会是更好的选择。当发生可怕的事情时,您可以将它们排队而不是收到无数封电子邮件。 - Tony Hopkinson
它是在分离的汇编中。 - J - C Sharper
我认为可以使用完整的文件路径来确定是哪个项目,但是我想知道是否有更好的方法只获取项目名称。 - J - C Sharper
6个回答

41

如果您的日志记录代码位于一个单独的库程序集中,并且直接从ASP.NET程序集调用到您的库程序集,同时标记该方法不会被内联,则可以使用Assembly.GetCallingAssembly

[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;
}

在您的库中的任何可能想要记录项目名称的入口点处,您必须记录调用程序集并将其标记为NoInlining,然后在内部传递它。

如果您使用的是.NET 4.5,则有一种替代方法:CallerFilePath。 它对入口点有相同的限制,并返回计算机上源路径而不是程序集名称(这可能没有那么有用),但更容易知道它会起作用(因为它编译它,就像可选参数一样被编译),并允许内联:

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>" +
...

1
根据他调用代码的方式,那可能行不通。如果他在错误处理程序中运行,则调用程序集将是 System.Web 或他的日志记录程序集。 - SLaks
@SLaks在他的错误处理代码库中的任何公共入口点处,应记录Assembly.GetCallingAssembly()(然后根据需要在内部传递它)。那样行得通吗? - Tim S.
@J-CSharper,你得到了什么程序集名称?哪个程序集包含调用“JndGetEmailTextForDebuggingExceptionError”的方法? - Tim S.
等我再试一下,稍等片刻。 - J - C Sharper
它运行正常。谢谢Tim,很抱歉第一次没有正确测试它。感谢大家的支持。你们是我曾经遇到过的最好的代码支持论坛。 - J - C Sharper
显示剩余6条评论

38

对于寻找 ASP.NET Core 兼容解决方案的任何人,以下内容应该有效;

System.Reflection.Assembly.GetEntryAssembly().GetName().Name


.NET Core API 参考文档


15

这应该足够了

string projectName = Assembly.GetCallingAssembly().GetName().Name;

编辑*如果你正在从另一个程序集中运行此代码,那么你应该使用GetCallingAssembly方法。


1
这可能不够好;他的日志记录代码很可能(希望如此)在一个单独的库程序集中。 - SLaks

6
您可以使用

标签

HttpContext.Current.ApplicationInstance.GetType().Assembly.GetName().Name

如果返回的是App_global.asax....,请将其更改为
HttpContext.Current.ApplicationInstance.GetType().BaseType.Assembly.GetName().Name

如果您没有运行在HTTP请求中,您需要一些方法来获取HttpContext

如果您正在使用Web网站项目(而不是Web应用程序),结果将有所不同。

您还可以使用HttpRuntime.AppDomainAppPath来获取已部署站点的磁盘上的物理路径;这将在任何地方都起作用。


1
当我在名为WebApplication1的项目下运行时,这给了我System.Web..? - dtsg
@dtsg:该项目在Global.asax中是否注册了一个HttpApplication的后代? - SLaks
这是一个没有 Global.asax 文件的新项目。 - dtsg
@dtsg:这就可以解释了。据我所知,所有真正的项目都会有一个Global.asax文件。 - SLaks
好的。从另一个程序集(您的第二个示例)调用它并返回App_global.asax.xw877d4c - dtsg
显示剩余2条评论

6

反射是找出产品名称、公司名称版本等信息的最佳方法。

public static string ProductName
{
 get
 {
    AssemblyProductAttribute myProduct =(AssemblyProductAttribute)AssemblyProductAttribute.GetCustomAttribute(Assembly.GetExecutingAssembly(),
     typeof(AssemblyProductAttribute));
      return myProduct.Product;
  }
}

还有一种方法,就是直接获取项目名称

string projectName=System.IO.Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().Location).ToString();

2
如果它在一个单独的程序集中(这很可能),那么这样做是行不通的。 - SLaks
此外,ASP.Net项目很少具有这个属性。 - SLaks
如果是单一程序集,在ASP.NET中运行良好。 - Brent

1

我在这里提供我的答案。

对于那些在项目中使用多个DLL的人,正确的答案是:

string projectName = Assembly.GetExecutingAssembly().FullName.Split(',')[0];


(注:该代码片段可用于获取当前执行程序集的名称。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接