【问题标题】:Source file information missing in StackTrace, when PDB loaded from another folder当从另一个文件夹加载 PDB 时,StackTrace 中缺少源文件信息
【发布时间】:2013-11-25 18:57:19
【问题描述】:

我正在尝试在运行时获取堆栈跟踪信息。

我正在使用以下代码,这在默认项目配置中运行良好:

  StackTrace trace = new System.Diagnostics.StackTrace(true);
  StackFrame frame = trace.GetFrame(0);
  int line = frame.GetFileLineNumber();
  Console.WriteLine(line);

但是,我正在尝试构建的解决方案被配置为将二进制文件和 PDB 放到单独的文件夹中:

<PropertyGroup>
  ...
  <OutputPath>Binaries\$(Configuration)\bin\</OutputPath>
  <IntermediateOutputPath>Binaries\$(Configuration)\obj\$(MSBuildProjectName)\</IntermediateOutputPath>
  <PdbFile>Binaries\$(Configuration)\pdb\$(MSBuildProjectName).pdb</PdbFile>
  <SkipCopyingSymbolsToOutputDirectory>true</SkipCopyingSymbolsToOutputDirectory>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
  <PlatformTarget>AnyCPU</PlatformTarget>
  <DebugSymbols>true</DebugSymbols>
  <DebugType>full</DebugType>
  <Optimize>false</Optimize>
  <DefineConstants>DEBUG;TRACE</DefineConstants>
  <ErrorReport>prompt</ErrorReport>
  <WarningLevel>4</WarningLevel>
</PropertyGroup>

我可以在 Visual Studio 的 Modules 窗口中看到 PDB 已加载。但是,frame 变量不包含有关源文件(文件名、行和列)的信息。如果我将 .pdb 和 .exe 复制到同一个文件夹,则输出再次正确。

因此,据我了解:

  • PDB 是正确的(包含必要的信息),因为当我将文件放入同一文件夹时它可以工作
  • Visual Studio 能够加载 PDB,所以搜索路径也应该是正确的

我搜索了互联网(包括http://msdn.microsoft.com/en-us/library/ee416588.aspxDisplay lines number in Stack Trace for .NET assembly in Release mode),但所有文章主要关注从正确位置加载 PDB(就我而言,情况并非如此)。我不明白的是为什么虽然加载了PDB,却没有获得源文件/行信息。

所以,问题是:当 .pdb 从不同位置加载时,是否可以获得包含有关源文件信息的堆栈跟踪?如果不是,为什么?

【问题讨论】:

  • 哪个版本的 Visual Studio 和哪个版本的 .Net?
  • 我正在使用 VS2012 并针对 .Net 4.0

标签: c# .net visual-studio debugging debug-symbols


【解决方案1】:

您只是让 CLR 很难找到 PDB。您在调试器的“模块”窗口中看到的信息不相关,仅对调试器重要。 CLR 有自己的机制来定位和读取 PDB。必然如此,这仍然需要在用户机器上没有调试器的情况下工作。

技术上可以通过设置环境变量来告诉 CLR 在哪里查找。假设您将 PDB 文件存储在名为“pdbs”的子目录中,那么您可以将此代码放入 Main() 方法中:

var appdir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
var pdbdir = System.IO.Path.Combine(appdir, "pdbs");
Environment.SetEnvironmentVariable("_NT_SYMBOL_PATH", pdbdir);

或者只是不要费力,将它们放在与您的 EXE 相同的目录中。

【讨论】:

  • 感谢您的详细解释。不知道 CLR 使用不同的算法来定位 PDB。设置_NT_SYMBOL_PATH 完美!但是,为了完全理解,CLR 在 PDB 查找期间是否会查看任何其他文件夹(例如 、<_nt_symbol_path>、...还有什么其他的吗?)。不幸的是,我找不到任何与 CLR 机制相关的内容。
【解决方案2】:

是否可以获得包含有关信息的堆栈跟踪 源文件,当 .pdb 从不同位置加载时?

是的,但您需要告诉 Visual Studio 该位置在哪里,如果它不在当前目录中。通过添加备用PDB文件夹的位置,在VS中指定Tools->Options->Symbols中的位置。

有关详细信息,请参阅Specify Symbol (.pdb) and Source Files in the Visual Studio Debugger 中标题为“指定符号位置和加载行为”的部分。

【讨论】:

  • Visual Studio 不会出现在用户的机器上;)
  • 谢谢,但这无济于事,因为正如我在问题中提到的,VS 已经可以加载正确的 PDB(因为项目是在我的机器上构建的)
猜你喜欢
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 2017-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多