我正在尝试在运行时获取堆栈跟踪信息。
我正在使用以下代码,这在默认项目配置中工作正常:
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复制到同一文件夹,则输出再次正确。
因此,据我所知:
我搜索了互联网(包括http://msdn.microsoft.com/en-us/library/ee416588.aspx和Display lines number in Stack Trace for .NET assembly in Release mode),但所有文章都主要关注从正确位置加载PDB(就我而言,事实并非如此)。我不明白的是为什么无法获取源文件/行信息,尽管加载了PDB。
所以,问题是:当从不同位置加载.pdb时,是否有可能获得包含源文件信息的Stack Trace?如果没有,为什么?
答案 0 :(得分:2)
您只是让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相同的目录中。
答案 1 :(得分:1)
是否可以获取包含有关信息的Stack Trace 源文件,当.pdb从不同的位置加载?
是的,但是如果它不在当前目录中,则需要告诉Visual Studio该位置的位置。通过添加备用PDB文件夹的位置,在VS中指定Tools
- &gt; Options
- &gt; Symbols
中的位置。
有关详细信息,请参阅“{3}}中指定符号位置和加载行为”一节。