在C#中编写的代码中获取行号和文件信息

12 浏览
0 Comments

在C#中编写的代码中获取行号和文件信息

我想做的事情举例如下:

MessageBox.Show("错误行号为 " + CurrentLineNumber);

在上述代码中,CurrentLineNumber 应该是这段代码源代码中的行号。

我该如何实现这个?

0
0 Comments

问题的原因是在代码中获取行号和文件信息需要使用System.Diagnostics命名空间下的StackFrame类和GetFileLineNumber方法。但是这种方法需要.pdb文件的支持,而.pdb文件通常不会生成或复制到生产服务器上。

解决方法是在代码中先判断是否处于调试模式,如果是则使用上述方法获取行号和文件信息;如果不是调试模式,则可以使用其他方法来获取行号和文件信息,如使用异常处理中的StackTrace类来获取调用栈信息。

以下是解决方法的代码示例:

// 判断是否处于调试模式
#if DEBUG
    int lineNumber = (new System.Diagnostics.StackFrame(0, true)).GetFileLineNumber();
    string fileName = (new System.Diagnostics.StackFrame(0, true)).GetFileName();
    Console.WriteLine("Line Number: " + lineNumber);
    Console.WriteLine("File Name: " + fileName);
#else
    // 使用异常处理获取调用栈信息
    try
    {
        throw new Exception();
    }
    catch (Exception ex)
    {
        var stackTrace = new System.Diagnostics.StackTrace(ex);
        var frame = stackTrace.GetFrame(0);
        int lineNumber = frame.GetFileLineNumber();
        string fileName = frame.GetFileName();
        Console.WriteLine("Line Number: " + lineNumber);
        Console.WriteLine("File Name: " + fileName);
    }
#endif

通过以上代码,在调试模式下可以直接使用StackFrame类的GetFileLineNumber方法来获取行号和文件信息,而在非调试模式下,可以通过异常处理来获取调用栈信息,进而获取行号和文件信息。这样就可以在生产服务器上获取到行号和文件信息,而无需依赖.pdb文件的支持。

0
0 Comments

问题的原因是需要在代码中获取行号和文件信息。解决方法是使用StackFrame类的GetFileLineNumber和GetFileName方法来获取行号和文件信息。另外,对于使用.Net 4.5或更高版本的用户,还可以考虑使用CallerFilePath、CallerMethodName和CallerLineNumber属性来获取文件路径、方法名和行号信息。

在代码中,可以使用以下方法来获取行号和文件信息:

private static void ReportError(string message)
{
     StackFrame callStack = new StackFrame(1, true);
     MessageBox.Show("Error: " + message + ", File: " + callStack.GetFileName() 
          + ", Line: " + callStack.GetFileLineNumber());
}

这段代码中,StackFrame的构造函数的第一个参数表示调用深度(这里为1),第二个参数表示需要文件信息。调用GetFileName和GetFileLineNumber方法来获取文件名和行号信息。

对于使用.Net 4.5或更高版本的用户,可以使用CallerFilePath、CallerMethodName和CallerLineNumber属性来获取文件路径、方法名和行号信息。示例如下:

public void TraceMessage(string message,
        [CallerMemberName] string callingMethod = "",
        [CallerFilePath] string callingFilePath = "",
        [CallerLineNumber] int callingFileLineNumber = 0)
{
    // Write out message
}

在这个示例中,方法参数上使用了CallerMemberName、CallerFilePath和CallerLineNumber属性。这些属性必须指定默认值,并且必须是string类型的CallerMemberName和CallerFilePath属性,以及int类型的CallerLineNumber属性。编译器会在编译时根据调用代码插入相应的值,这意味着它可以通过混淆工具工作。

无论是否出现错误,这些方法都可以获取行号和文件信息。StackFrame类只是查看当前执行的方法调用。StackFrame构造函数的第一个参数是调用深度(这里为1),第二个参数表示需要文件信息。

对于在Mono上编译StackFrame示例的用户,请确保在编译和运行时使用--debug选项。

需要注意的是,在.NET Core中不支持StackFrame类。可以使用Marc Gravell的解决方案来替代。

另外,使用默认值`= string.Empty`会抛出错误“默认参数'callingFilePath'的值必须是编译时常量”。可以将示例中的`= string.Empty`更改为使用双引号`""`来解决这个问题。

0
0 Comments

在.NET 4.5 / C# 5中,您可以通过编写一个使用新的调用者属性的实用方法来让编译器为您完成这项工作:

using System.Runtime.CompilerServices;
static void SomeMethodSomewhere()
{
    ShowMessage("Boo");
}
...
static void ShowMessage(string message,
    [CallerLineNumber] int lineNumber = 0,
    [CallerMemberName] string caller = null)
{
     MessageBox.Show(message + " at line " + lineNumber + " (" + caller + ")");
}

这将显示如下信息:

Boo at line 39 (SomeMethodSomewhere)

还有一个`[CallerFilePath]`,它告诉您原始代码文件的路径。

为了方便潜水者,您必须在定义实用方法的类的顶部包含`using System.Runtime.CompilerServices`。

感谢您的答案。是否可能还可以了解对象名称?哦,我搞混了。我想知道的是asp.net 4.5网站。全局错误捕获。捕获错误引起的对象名称吗?

不是的,只有我上面提到的这3个。

这需要运行时环境也是4.5吗?还是这是一个编译器功能?

对于潜水者的好处,您必须在定义实用方法的类的顶部包含`using System.Runtime.CompilerServices`。

0