ClrMd выдает исключение при создании среды выполнения
Я использую библиотеку диагностики памяти 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
2 ответа
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);
}
}
Я знаю, это ужасно и зависит от Reflection. Но, по крайней мере, пока это работает, и вам не нужно менять код.
Вы можете решить эту проблему, загрузив последнюю версию Microsoft.Diagnostics.Runtime.dll
(v0.8.31-бета): https://www.nuget.org/packages/Microsoft.Diagnostics.Runtime
Версия v0.8.31-бета отмечена рядом устаревших функций, так как, как упоминал Алоис Краус, runtime.GetHeap()
может сломаться. Я смог решить эту проблему, создав мою среду выполнения следующим образом:
DataTarget target = DataTarget.AttachProcess(pid, timeout, mode);
ClrRuntime runtime = target.ClrVersions.First().CreateRuntime();
ClrHeap heap = runtime.GetHeap();
Вся чушь с TryGetDacLocation()
сейчас ненужно.