C# 从PDB文件中检索局部变量名
我目前正试图从IL字节码和PDB文件中检索源代码, 我已经到了可以从IL和反射生成源代码的地步 我知道局部变量名的名称包含在pdb文件中。 我的问题是我怎样才能找回它?我应该使用什么LIB来处理pdb文件(如果有),还是应该自己编写代码?在哪里可以找到有关pdb文件格式的信息? 目前,在生成的源代码中,我对局部变量使用自动生成的值,但我想改变这一点,因为我相信,如果您可以使用pdb文件,就有可能找到这些信息。 我试着在谷歌上搜索,但没有找到任何有用的信息C# 从PDB文件中检索局部变量名,c#,.net,cil,C#,.net,Cil,我目前正试图从IL字节码和PDB文件中检索源代码, 我已经到了可以从IL和反射生成源代码的地步 我知道局部变量名的名称包含在pdb文件中。 我的问题是我怎样才能找回它?我应该使用什么LIB来处理pdb文件(如果有),还是应该自己编写代码?在哪里可以找到有关pdb文件格式的信息? 目前,在生成的源代码中,我对局部变量使用自动生成的值,但我想改变这一点,因为我相信,如果您可以使用pdb文件,就有可能找到这些信息。 我试着在谷歌上搜索,但没有找到任何有用的信息 提前感谢您的回复;) 看看Codeple
提前感谢您的回复;) 看看Codeplex上的项目。它有一个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);
}
}
我知道这个问题是在2011年提出的。现在是2019年,有两个选项可以从方法中检索局部变量 首先,让我们定义
VariableInfo
以保留局部变量参数:
public class VariableInfo : IEquatable<VariableInfo>
{
public int Index { get; }
public string Name { get; }
public Type Type { get; }
public VariableInfo(int index, Type type, string name) =>
(Index, Type, Name) = (index, type, name);
public override bool Equals(object obj) =>
Equals(obj as VariableInfo);
public bool Equals(VariableInfo info) =>
info != null &&
Index.Equals(info.Index) &&
Name.Equals(info.Name) &&
Type.Equals(info.Type);
public override int GetHashCode()
{
unchecked
{
var hash = 17;
hash = 23 * hash + Index.GetHashCode();
hash = 23 * hash + Name.GetHashCode();
hash = 23 * hash + Type.GetHashCode();
return hash;
}
}
public override string ToString() =>
$"Index {Index}, Type {Type}, Name {Name}";
}
现在可以通过以下方式实现:
public class MicrosoftDebuggingReader : ILocalsReader
{
public VariableInfo[] Read(MethodBase info)
{
var il = info.GetMethodBody().LocalVariables.ToArray();
return SymbolAccess
.GetReaderForFile(info.DeclaringType.Assembly.Location)
.GetMethod(new SymbolToken(info.MetadataToken))
.RootScope
.GetInnerScopesRecursive()
.SelectMany(scope => scope.GetLocals())
.Select(local =>
new VariableInfo(local.AddressField1,
il[local.AddressField1].LocalType,
local.Name))
.ToArray();
}
}
public class MonoCecilReader : ILocalsReader
{
public VariableInfo[] Read(MethodBase info)
{
var method = info.GetMethodDefinition();
method.Module.ReadSymbols();
var pdb = Path.ChangeExtension(info.DeclaringType.Assembly.Location, "pdb");
new PdbReaderProvider().GetSymbolReader(method.Module, pdb)
.Read(method);
var il = info.GetMethodBody().LocalVariables;
return Read(method, il);
}
public VariableInfo[] Read(MethodDefinition method, IList<LocalVariableInfo> il)
{
return method
.DebugInformation
.Scope
.GetInnerScopesRecursive()
.SelectMany(scope => scope.Variables)
.Select(local =>
new VariableInfo(local.Index,
il[local.Index].LocalType,
local.Name))
.ToArray();
}
}
其中,GetInnerScopesRecursive
是一种扩展方法:
internal static class SymbolScopeExtensions
{
public static IEnumerable<ISymbolScope> GetInnerScopesRecursive(this ISymbolScope scope)
{
yield return scope;
foreach (var innerScope in scope.GetChildren()
.SelectMany(innerScope => innerScope.GetInnerScopesRecursive()))
yield return innerScope;
}
}
public static class MethodDefinitionExtensions
{
public static MethodDefinition GetMethodDefinition(this MethodBase info) =>
AssemblyDefinition
.ReadAssembly(info.DeclaringType.Assembly.Location)
.Modules
.SelectMany(module => module.GetTypes())
.Single(type => type.FullNameMatches(info.DeclaringType))
.Methods
.FirstOrDefault(method =>
method.Name.Equals(info.Name) &&
method.ReturnType.FullName.Equals(info.GetReturnType().FullName) &&
method.Parameters.Select(parameter => parameter.ParameterType.FullName)
.SequenceEqual(info.GetParameters().Select(parameter => parameter.ParameterType.FullName)));
}
public static class MethodBaseExtensions
{
public static Type GetReturnType(this MethodBase method)
{
if (method is MethodInfo info)
return info.ReturnType;
if (method is ConstructorInfo ctor)
return typeof(void);
throw new ArgumentException($"Argument {nameof(method)} has unsupported type {method.GetType()}.");
}
}
internal static class TypeDefinitionExtensions
{
public static bool FullNameMatches(this TypeDefinition typeDefinition, Type type) =>
typeDefinition.FullName.Replace("/", "").Equals(type.FullName.Replace("+", ""));
}
internal static class ScopeDebugInformationExtensions
{
public static IEnumerable<ScopeDebugInformation> GetInnerScopesRecursive(this ScopeDebugInformation scope)
{
yield return scope;
foreach (var innerScope in scope.Scopes
.SelectMany(innerScope => innerScope.GetInnerScopesRecursive()))
yield return innerScope;
}
}
其中GetMethodDefinition
是一个扩展方法:
internal static class SymbolScopeExtensions
{
public static IEnumerable<ISymbolScope> GetInnerScopesRecursive(this ISymbolScope scope)
{
yield return scope;
foreach (var innerScope in scope.GetChildren()
.SelectMany(innerScope => innerScope.GetInnerScopesRecursive()))
yield return innerScope;
}
}
public static class MethodDefinitionExtensions
{
public static MethodDefinition GetMethodDefinition(this MethodBase info) =>
AssemblyDefinition
.ReadAssembly(info.DeclaringType.Assembly.Location)
.Modules
.SelectMany(module => module.GetTypes())
.Single(type => type.FullNameMatches(info.DeclaringType))
.Methods
.FirstOrDefault(method =>
method.Name.Equals(info.Name) &&
method.ReturnType.FullName.Equals(info.GetReturnType().FullName) &&
method.Parameters.Select(parameter => parameter.ParameterType.FullName)
.SequenceEqual(info.GetParameters().Select(parameter => parameter.ParameterType.FullName)));
}
public static class MethodBaseExtensions
{
public static Type GetReturnType(this MethodBase method)
{
if (method is MethodInfo info)
return info.ReturnType;
if (method is ConstructorInfo ctor)
return typeof(void);
throw new ArgumentException($"Argument {nameof(method)} has unsupported type {method.GetType()}.");
}
}
internal static class TypeDefinitionExtensions
{
public static bool FullNameMatches(this TypeDefinition typeDefinition, Type type) =>
typeDefinition.FullName.Replace("/", "").Equals(type.FullName.Replace("+", ""));
}
internal static class ScopeDebugInformationExtensions
{
public static IEnumerable<ScopeDebugInformation> GetInnerScopesRecursive(this ScopeDebugInformation scope)
{
yield return scope;
foreach (var innerScope in scope.Scopes
.SelectMany(innerScope => innerScope.GetInnerScopesRecursive()))
yield return innerScope;
}
}
而GetReturnType
是一种扩展方法:
internal static class SymbolScopeExtensions
{
public static IEnumerable<ISymbolScope> GetInnerScopesRecursive(this ISymbolScope scope)
{
yield return scope;
foreach (var innerScope in scope.GetChildren()
.SelectMany(innerScope => innerScope.GetInnerScopesRecursive()))
yield return innerScope;
}
}
public static class MethodDefinitionExtensions
{
public static MethodDefinition GetMethodDefinition(this MethodBase info) =>
AssemblyDefinition
.ReadAssembly(info.DeclaringType.Assembly.Location)
.Modules
.SelectMany(module => module.GetTypes())
.Single(type => type.FullNameMatches(info.DeclaringType))
.Methods
.FirstOrDefault(method =>
method.Name.Equals(info.Name) &&
method.ReturnType.FullName.Equals(info.GetReturnType().FullName) &&
method.Parameters.Select(parameter => parameter.ParameterType.FullName)
.SequenceEqual(info.GetParameters().Select(parameter => parameter.ParameterType.FullName)));
}
public static class MethodBaseExtensions
{
public static Type GetReturnType(this MethodBase method)
{
if (method is MethodInfo info)
return info.ReturnType;
if (method is ConstructorInfo ctor)
return typeof(void);
throw new ArgumentException($"Argument {nameof(method)} has unsupported type {method.GetType()}.");
}
}
internal static class TypeDefinitionExtensions
{
public static bool FullNameMatches(this TypeDefinition typeDefinition, Type type) =>
typeDefinition.FullName.Replace("/", "").Equals(type.FullName.Replace("+", ""));
}
internal static class ScopeDebugInformationExtensions
{
public static IEnumerable<ScopeDebugInformation> GetInnerScopesRecursive(this ScopeDebugInformation scope)
{
yield return scope;
foreach (var innerScope in scope.Scopes
.SelectMany(innerScope => innerScope.GetInnerScopesRecursive()))
yield return innerScope;
}
}
而FullNameMatches
是一种扩展方法:
internal static class SymbolScopeExtensions
{
public static IEnumerable<ISymbolScope> GetInnerScopesRecursive(this ISymbolScope scope)
{
yield return scope;
foreach (var innerScope in scope.GetChildren()
.SelectMany(innerScope => innerScope.GetInnerScopesRecursive()))
yield return innerScope;
}
}
public static class MethodDefinitionExtensions
{
public static MethodDefinition GetMethodDefinition(this MethodBase info) =>
AssemblyDefinition
.ReadAssembly(info.DeclaringType.Assembly.Location)
.Modules
.SelectMany(module => module.GetTypes())
.Single(type => type.FullNameMatches(info.DeclaringType))
.Methods
.FirstOrDefault(method =>
method.Name.Equals(info.Name) &&
method.ReturnType.FullName.Equals(info.GetReturnType().FullName) &&
method.Parameters.Select(parameter => parameter.ParameterType.FullName)
.SequenceEqual(info.GetParameters().Select(parameter => parameter.ParameterType.FullName)));
}
public static class MethodBaseExtensions
{
public static Type GetReturnType(this MethodBase method)
{
if (method is MethodInfo info)
return info.ReturnType;
if (method is ConstructorInfo ctor)
return typeof(void);
throw new ArgumentException($"Argument {nameof(method)} has unsupported type {method.GetType()}.");
}
}
internal static class TypeDefinitionExtensions
{
public static bool FullNameMatches(this TypeDefinition typeDefinition, Type type) =>
typeDefinition.FullName.Replace("/", "").Equals(type.FullName.Replace("+", ""));
}
internal static class ScopeDebugInformationExtensions
{
public static IEnumerable<ScopeDebugInformation> GetInnerScopesRecursive(this ScopeDebugInformation scope)
{
yield return scope;
foreach (var innerScope in scope.Scopes
.SelectMany(innerScope => innerScope.GetInnerScopesRecursive()))
yield return innerScope;
}
}
而GetInnerScopesRecursive
是一种扩展方法:
internal static class SymbolScopeExtensions
{
public static IEnumerable<ISymbolScope> GetInnerScopesRecursive(this ISymbolScope scope)
{
yield return scope;
foreach (var innerScope in scope.GetChildren()
.SelectMany(innerScope => innerScope.GetInnerScopesRecursive()))
yield return innerScope;
}
}
public static class MethodDefinitionExtensions
{
public static MethodDefinition GetMethodDefinition(this MethodBase info) =>
AssemblyDefinition
.ReadAssembly(info.DeclaringType.Assembly.Location)
.Modules
.SelectMany(module => module.GetTypes())
.Single(type => type.FullNameMatches(info.DeclaringType))
.Methods
.FirstOrDefault(method =>
method.Name.Equals(info.Name) &&
method.ReturnType.FullName.Equals(info.GetReturnType().FullName) &&
method.Parameters.Select(parameter => parameter.ParameterType.FullName)
.SequenceEqual(info.GetParameters().Select(parameter => parameter.ParameterType.FullName)));
}
public static class MethodBaseExtensions
{
public static Type GetReturnType(this MethodBase method)
{
if (method is MethodInfo info)
return info.ReturnType;
if (method is ConstructorInfo ctor)
return typeof(void);
throw new ArgumentException($"Argument {nameof(method)} has unsupported type {method.GetType()}.");
}
}
internal static class TypeDefinitionExtensions
{
public static bool FullNameMatches(this TypeDefinition typeDefinition, Type type) =>
typeDefinition.FullName.Replace("/", "").Equals(type.FullName.Replace("+", ""));
}
internal static class ScopeDebugInformationExtensions
{
public static IEnumerable<ScopeDebugInformation> GetInnerScopesRecursive(this ScopeDebugInformation scope)
{
yield return scope;
foreach (var innerScope in scope.Scopes
.SelectMany(innerScope => innerScope.GetInnerScopesRecursive()))
yield return innerScope;
}
}
注意:
Microsoft.Samples.debug.CorApi下载量约为9k,最近一次更新是在2011年12月10日
下载量约3415k,最新提交时间为2019年8月5日Mono.Cecil