ClrMd 在创建运行时时抛出异常
ClrMd throws exception when creating runtime
我正在使用 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
ClrMD 目前不支持 .NET 4.6。有一个开放的拉取请求 on 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()
的废话现在都没有必要了。
我正在使用 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
ClrMD 目前不支持 .NET 4.6。有一个开放的拉取请求 on 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()
的废话现在都没有必要了。