Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从PDB文件中检索局部变量名_C#_.net_Cil - Fatal编程技术网

C# 从PDB文件中检索局部变量名

C# 从PDB文件中检索局部变量名,c#,.net,cil,C#,.net,Cil,我目前正试图从IL字节码和PDB文件中检索源代码, 我已经到了可以从IL和反射生成源代码的地步 我知道局部变量名的名称包含在pdb文件中。 我的问题是我怎样才能找回它?我应该使用什么LIB来处理pdb文件(如果有),还是应该自己编写代码?在哪里可以找到有关pdb文件格式的信息? 目前,在生成的源代码中,我对局部变量使用自动生成的值,但我想改变这一点,因为我相信,如果您可以使用pdb文件,就有可能找到这些信息。 我试着在谷歌上搜索,但没有找到任何有用的信息 提前感谢您的回复;) 看看Codeple

我目前正试图从IL字节码和PDB文件中检索源代码, 我已经到了可以从IL和反射生成源代码的地步 我知道局部变量名的名称包含在pdb文件中。 我的问题是我怎样才能找回它?我应该使用什么LIB来处理pdb文件(如果有),还是应该自己编写代码?在哪里可以找到有关pdb文件格式的信息? 目前,在生成的源代码中,我对局部变量使用自动生成的值,但我想改变这一点,因为我相信,如果您可以使用pdb文件,就有可能找到这些信息。 我试着在谷歌上搜索,但没有找到任何有用的信息


提前感谢您的回复;)

看看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日
  • Mono.Cecil
    下载量约3415k,最新提交时间为2019年8月5日