ClrMd在创建运行时抛出异常

本文关键字:抛出异常 运行时 创建 ClrMd | 更新日期: 2023-09-27 18:04:37

我正在使用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()
                );
            }
        }

我从这里得到了这个代码,它似乎对其他人有效,但它在指示行上为我抛出了一个异常,消息是This runtime is not initialized and contains no data.

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

ClrMd在创建运行时抛出异常

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

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

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 (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()现在是不必要的。

相关文章: