我目前正試圖從IL字節碼和PDB文件檢索源代碼, 我我趕到那裏我可以生成從IL源代碼和反射 點我知道的名字本地變量名稱包含在pdb文件中。 我的問題是我如何找回它?我應該使用什麼庫來處理pdb文件(如果有)或者我應該自己編寫代碼?我在哪裏可以找到關於pdb文件格式的信息? 當前在生成的源代碼我使用自動生成的值爲本地變量,但我想改變,因爲我相信如果您有pdb文件在您的處置可以找到該信息。 我試圖看看谷歌,但我沒有找到任何有用的信息。從PDB文件檢索局部變量名
預先感謝您的答覆;)
我目前正試圖從IL字節碼和PDB文件檢索源代碼, 我我趕到那裏我可以生成從IL源代碼和反射 點我知道的名字本地變量名稱包含在pdb文件中。 我的問題是我如何找回它?我應該使用什麼庫來處理pdb文件(如果有)或者我應該自己編寫代碼?我在哪裏可以找到關於pdb文件格式的信息? 當前在生成的源代碼我使用自動生成的值爲本地變量,但我想改變,因爲我相信如果您有pdb文件在您的處置可以找到該信息。 我試圖看看谷歌,但我沒有找到任何有用的信息。從PDB文件檢索局部變量名
預先感謝您的答覆;)
看看CodePlex上,基於CCI項目。它有一個PDBReader項目。
下面介紹如何在System.Diagnostics.SymbolStore
使用類型來讀取一個MethodInfo的局部變量名:
public class LocalVariableNameReader
{
Dictionary<int, string> _names = new Dictionary<int, string>();
public string this [int index]
{
get
{
if (!_names.ContainsKey (index)) return null;
return _names [index];
}
}
public LocalVariableNameReader (MethodInfo m)
{
ISymbolReader symReader = SymUtil.GetSymbolReaderForFile (m.DeclaringType.Assembly.Location, null);
ISymbolMethod met = symReader.GetMethod (new SymbolToken (m.MetadataToken));
VisitLocals (met.RootScope);
}
void VisitLocals (ISymbolScope iSymbolScope)
{
foreach (var s in iSymbolScope.GetLocals()) _names [s.AddressField1] = s.Name;
foreach (var c in iSymbolScope.GetChildren()) VisitLocals (c);
}
}
的SymUtil
類來自this example。
編輯:上述鏈接已損壞。從谷歌緩存:
很久以前,我一直在尋找如何才能處理PDB文件 獲得額外的信息反映根本無法提供。 現在我難倒了邁克斯托爾的一個5歲的職位 (here) 突然全部變得清晰。我已經整理了一個小例子,其中 使用.net 4.0來讀取方法主體代碼,因爲它是源代碼 ,從編譯程序集的位置開始。請注意,爲了使此 正常工作,您必須具有可用的程序集的pdb。另外 請確保你添加了一個參考ISymWrapper和您的項目 是針對.Net 4.0框架,而不是.Net 4.0客戶端。
using System;
using System.Diagnostics.SymbolStore;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
namespace PdbTest
{
class Program
{
static void Main(string[] args)
{
Assembly ass = Assembly.GetExecutingAssembly();
ISymbolReader symreader = SymUtil.GetSymbolReaderForFile(ass.Location, null);
MethodInfo m = ass.GetType("PdbTest.TestClass").GetMethod("GetStringRepresentation");
ISymbolMethod met = symreader.GetMethod(new SymbolToken(m.MetadataToken));
int count = met.SequencePointCount;
ISymbolDocument[] docs = new ISymbolDocument[count];
int[] offsets = new int[count];
int[] lines = new int[count];
int[] columns = new int[count];
int[] endlines = new int[count];
int[] endcolumns = new int[count];
met.GetSequencePoints(offsets, docs, lines, columns, endlines, endcolumns);
StreamReader reader = new StreamReader(docs[0].URL);
string[] linesOfCode = reader.ReadToEnd().Split('n');
reader.Close();
Console.WriteLine("The content of method PdbTest.TestClass.GetStringRepresentation");
for (int i = lines[0]; i < endlines[count - 1] - 1; i++)
{
Console.WriteLine(linesOfCode[i]);
}
}
}
#region test class
public enum MyEnum
{
Apples,
Oranges
}
public partial class TestClass
{
public string GetStringRepresentation(MyEnum e)
{
MyEnum e2 = MyEnum.Apples;
return e.ToString() + e2.ToString();
}
}
#endregion test class
#region Get a symbol reader for the given module
// Encapsulate a set of helper classes to get a symbol reader from a file.
// The symbol interfaces require an unmanaged metadata interface.
static class SymUtil
{
static class NativeMethods
{
[DllImport("ole32.dll")]
public static extern int CoCreateInstance(
[In] ref Guid rclsid,
[In, MarshalAs(UnmanagedType.IUnknown)] Object pUnkOuter,
[In] uint dwClsContext,
[In] ref Guid riid,
[Out, MarshalAs(UnmanagedType.Interface)] out Object ppv);
}
// Wrapper.
public static ISymbolReader GetSymbolReaderForFile(string pathModule, string searchPath)
{
return SymUtil.GetSymbolReaderForFile(
new System.Diagnostics.SymbolStore.SymBinder(), pathModule, searchPath);
}
// We demand Unmanaged code permissions because we're reading from the file
// system and calling out to the Symbol Reader
// @TODO - make this more specific.
[System.Security.Permissions.SecurityPermission(
System.Security.Permissions.SecurityAction.Demand,
Flags = System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)]
public static ISymbolReader GetSymbolReaderForFile(
System.Diagnostics.SymbolStore.SymBinder binder, string pathModule, string searchPath)
{
// Guids for imported metadata interfaces.
Guid dispenserClassID = new Guid(0xe5cb7a31, 0x7512, 0x11d2, 0x89,
0xce, 0x00, 0x80, 0xc7, 0x92, 0xe5, 0xd8); // CLSID_CorMetaDataDispenser
Guid dispenserIID = new Guid(0x809c652e, 0x7396, 0x11d2, 0x97, 0x71,
0x00, 0xa0, 0xc9, 0xb4, 0xd5, 0x0c); // IID_IMetaDataDispenser
Guid importerIID = new Guid(0x7dac8207, 0xd3ae, 0x4c75, 0x9b, 0x67,
0x92, 0x80, 0x1a, 0x49, 0x7d, 0x44); // IID_IMetaDataImport
// First create the Metadata dispenser.
object objDispenser;
NativeMethods.CoCreateInstance(ref dispenserClassID, null, 1,
ref dispenserIID, out objDispenser);
// Now open an Importer on the given filename. We'll end up passing this importer
// straight through to the Binder.
object objImporter;
IMetaDataDispenser dispenser = (IMetaDataDispenser)objDispenser;
dispenser.OpenScope(pathModule, 0, ref importerIID, out objImporter);
IntPtr importerPtr = IntPtr.Zero;
ISymbolReader reader;
try
{
// This will manually AddRef the underlying object, so we need to
// be very careful to Release it.
importerPtr = Marshal.GetComInterfaceForObject(objImporter,
typeof(IMetadataImport));
reader = binder.GetReader(importerPtr, pathModule, searchPath);
}
finally
{
if (importerPtr != IntPtr.Zero)
{
Marshal.Release(importerPtr);
}
}
return reader;
}
}
#region Metadata Imports
// We can use reflection-only load context to use reflection to query for
// metadata information rather
// than painfully import the com-classic metadata interfaces.
[Guid("809c652e-7396-11d2-9771-00a0c9b4d50c"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
interface IMetaDataDispenser
{
// We need to be able to call OpenScope, which is the 2nd vtable slot.
// Thus we need this one placeholder here to occupy the first slot..
void DefineScope_Placeholder();
//STDMETHOD(OpenScope)( // Return code.
//LPCWSTR szScope, // [in] The scope to open.
// DWORD dwOpenFlags, // [in] Open mode flags.
// REFIID riid, // [in] The interface desired.
// IUnknown **ppIUnk) PURE; // [out] Return interface on success.
void OpenScope([In, MarshalAs(UnmanagedType.LPWStr)] String szScope,
[In] Int32 dwOpenFlags, [In] ref Guid riid,
[Out, MarshalAs(UnmanagedType.IUnknown)] out Object punk);
// Don't need any other methods.
}
// Since we're just blindly passing this interface through managed code to the Symbinder,
// we don't care about actually importing the specific methods.
// This needs to be public so that we can call Marshal.GetComInterfaceForObject() on
// it to get the underlying metadata pointer.
[Guid("7DAC8207-D3AE-4c75-9B67-92801A497D44"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
[CLSCompliant(true)]
public interface IMetadataImport
{
// Just need a single placeholder method so that it doesn't complain
// about an empty interface.
void Placeholder();
}
#endregion
#endregion Get a symbol reader for the given module
}