在.net堆中查找类型的实例数据 [英] Finding a type's instance data in .net heap

查看:49
本文介绍了在.net堆中查找类型的实例数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下两个Foo和Bar类

Let's say I have two class Foo and Bar as follows

public class Foo
{
    private Bar _bar;
    private string _whatever = "whatever";
    public Foo()
    {
        _bar = new Bar();
    }

    public Bar TheBar
        {
            get
            {
                return _bar;
            }

        }
}

public class Bar
{
    public string Name { get; set; }
}

我有一个附加到使用这些类的进程的应用程序.我想在.NET堆中查看Foo类型的所有实例,并检查所有的TheBar.Name属性或_whatever字段.NET堆中存在的Foo实例.我可以找到类型,但不确定如何获取实例并查看其属性.有什么想法吗?

I have an application that attaches to a process that is using these classes. I would like to see all instances of Foo type in .NET heap and inspect the TheBar.Name property or _whatever field of all Foo instances present in .NET heap. I can find the type but I am not sure how to get the instance and see its properties. Any ideas how?

using (DataTarget target = DataTarget.AttachToProcess(processId, 30000))
{
    string dacLocation = target.ClrVersions[0].TryGetDacLocation();
    ClrRuntime runtime = target.CreateRuntime(dacLocation);

    if (runtime != null)
    {
        ClrHeap heap = runtime.GetHeap();
        foreach (ulong obj in heap.EnumerateObjects())
        {
            ClrType type = heap.GetObjectType(obj);
            if (type.Name.Compare("Foo") == 0 )
            {
                // I would like to see value of TheBar.Name property or _whatever field of all instances of Foo type in the heap. How can I do it?
            }
        }
    }
}

推荐答案

我认为您无法直接获取属性值,因为这将需要您运行代码,并且目标甚至可能不是进程而是转储文件.

I don't think you can get property values directly because that would require you to run code and the target might not even be a process but a dump file.

您绝对可以获取对象的字段及其值.ClrType有一个Fields属性,您可以使用它遍历字段.然后,您可以为HasSimpleValue为true的字段调用GetFieldValue.

You can definitely get an object's fields and their values. ClrType has a Fields property which you can use to loop through fields. Then you can call GetFieldValue for fields where HasSimpleValue is true.

一个简单的例子:

private static void PrintFieldsForType(ClrRuntime runtime, string targetType)
{
    ClrHeap heap = runtime.GetHeap();
    foreach (var ptr in heap.EnumerateObjects())
    {
        ClrType type = heap.GetObjectType(ptr);
        if (type.Name == targetType)
        {
            foreach(var field in type.Fields)
            {
                if (field.HasSimpleValue)
                {
                    object value = field.GetFieldValue(ptr);
                    Console.WriteLine("{0} ({1}) = {2}", field.Name, field.Type.Name, value);
                }
                else
                {
                    Console.WriteLine("{0} ({1})", field.Name, field.Type.Name);
                }
            }
        }
    }
}

因此,您可以查找包含名称","_ name"或类似名称的字段.如果它是自动实现的属性,则名称将类似于< Name> k__BackingField .

So you could look for a field that has "Name", "_name", or something similar in it. If it is an auto-implemented property, the name will be something like <Name>k__BackingField.

您的场景要复杂一点,因为您想进入另一个对象.为此,我们可以递归检查字段.但是请注意,在一般情况下,您可能希望跟踪访问过的对象,以免无限期递归.

Your scenario is a little more complicated in that you want to go into another object. To do that we can recursively inspect the fields. However note that in the general case you would want to keep track of which objects you've visited so you don't recurse indefinitely.

以下是一个更适合此示例:

Here is an example that is more appropriate for this:

private static void PrintFieldsForType(ClrRuntime runtime, TextWriter writer, string targetType)
{
    ClrHeap heap = runtime.GetHeap();
    foreach (var ptr in heap.EnumerateObjects())
    {
        ClrType type = heap.GetObjectType(ptr);
        if (type.Name == targetType)
        {
            writer.WriteLine("{0}:", targetType);
            PrintFields(type, writer, ptr, 0);
        }
    }
}

private static void PrintFields(ClrType type, TextWriter writer, ulong ptr, int indentLevel)
{
    string indent = new string(' ', indentLevel * 4);
    foreach (var field in type.Fields)
    {
        writer.Write(indent);
        if (field.IsObjectReference() && field.Type.Name != "System.String")
        {
            writer.WriteLine("{0} ({1})", field.Name, field.Type.Name);
            ulong nextPtr = (ulong)field.GetFieldValue(ptr);
            PrintFields(field.Type, writer, nextPtr, indentLevel + 1);
        }
        else if (field.HasSimpleValue)
        {
            object value = field.GetFieldValue(ptr);
            writer.WriteLine("{0} ({1}) = {2}", field.Name, field.Type.Name, value);
        }
        else
        {
            writer.WriteLine("{0} ({1})", field.Name, field.Type.Name);
        }
    }
}

这篇关于在.net堆中查找类型的实例数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆