【问题标题】:ClrMd throws exception when creating runtimeClrMd 创建运行时抛出异常
【发布时间】:2016-01-24 10:11:54
【问题描述】:

我正在使用 CLR 内存诊断库来获取正在运行的进程中所有线程的堆栈跟踪:

        var result = new Dictionary<int, string[]>();

        var pid = Process.GetCurrentProcess().Id;

        using (var dataTarget = DataTarget.AttachToProcess(pid, 5000, AttachFlag.Passive))
        {
            string dacLocation = dataTarget.ClrVersions[0].TryGetDacLocation();
            var runtime = dataTarget.CreateRuntime(dacLocation); //throws exception

            foreach (var t in runtime.Threads)
            {
                result.Add(
                    t.ManagedThreadId,
                    t.StackTrace.Select(f =>
                    {
                        if (f.Method != null)
                        {
                            return f.Method.Type.Name + "." + f.Method.Name;
                        }

                        return null;
                    }).ToArray()
                );
            }
        }

我从here 获得此代码,它似乎对其他人有用,但它在指定行对我抛出异常,并显示消息This runtime is not initialized and contains no data.

dacLocation 设置为C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\mscordacwks.dll

【问题讨论】:

  • 我的水晶球说你安装了.NET 4.6。这段代码目前死在永恒的DAC版本号上,4.6版本的DAC是4.6.81.0。看起来微软切换到“语义版本控制”。不是 ClrMD 所期望的,它需要找到 10000 或更大的内部版本号才能使用 V45Runtime 包装器类。我没有看到明显的解决方法,破解版本号也不起作用,微软需要更新 ClrMD 以处理 4.6。
  • 在此处查看相关示例代码:stackoverflow.com/questions/10315862/get-list-of-threads/…

标签: c# clrmd


【解决方案1】:

ClrMD 当前不支持 .NET 4.6。有一个开放的拉取请求on GitHub 只需一行就解决了这个问题。您当然可以克隆该项目并构建自己的 ClrMD,但不会出现此问题。

或者,我可以分享一个我过去几周一直在使用的临时 hack:

public static ClrRuntime CreateRuntimeHack(this DataTarget target, string dacLocation, int major, int minor)
{
    string dacFileNoExt = Path.GetFileNameWithoutExtension(dacLocation);
    if (dacFileNoExt.Contains("mscordacwks") && major == 4 && minor >= 5)
    {
        Type dacLibraryType = typeof(DataTarget).Assembly.GetType("Microsoft.Diagnostics.Runtime.DacLibrary");
        object dacLibrary = Activator.CreateInstance(dacLibraryType, target, dacLocation);
        Type v45RuntimeType = typeof(DataTarget).Assembly.GetType("Microsoft.Diagnostics.Runtime.Desktop.V45Runtime");
        object runtime = Activator.CreateInstance(v45RuntimeType, target, dacLibrary);
        return (ClrRuntime)runtime;
    }
    else
    {
        return target.CreateRuntime(dacLocation);
    }
}

我知道,这很可怕,并且依赖于反射。但至少现在它可以工作,而且您不必更改代码。

【讨论】:

  • 更新版本 Microsoft.Diagnostics.Runtime.dll 0.08.31 15.10.2015 01:48 可以获得运行时,但在 HasArrayComponentMethoTables.get 中的 runtime.GetHeap() 中出现 NullReferenceException 失败。现在使用了正确的 V45Runtime 实例,但它仍然中断。至少 4.6.96.0 是这种情况。这是一个已知问题吗?
【解决方案2】:

您可以通过下载Microsoft.Diagnostics.Runtime.dll (v0.8.31-beta) 的最新版本来解决此问题:https://www.nuget.org/packages/Microsoft.Diagnostics.Runtime

版本 v0.8.31-beta 标记了许多已过时的功能,因此正如 Alois Kraus 所提到的,runtime.GetHeap() 可能会中断。我可以通过按如下方式创建运行时来解决此问题:

DataTarget target = DataTarget.AttachProcess(pid, timeout, mode);
ClrRuntime runtime = target.ClrVersions.First().CreateRuntime();
ClrHeap heap = runtime.GetHeap();

TryGetDacLocation() 的所有废话现在都没有必要了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    • 2015-06-03
    • 2014-04-17
    • 2014-10-28
    • 2023-03-10
    • 1970-01-01
    • 2013-10-28
    相关资源
    最近更新 更多