Microsoft.Diagnostics.Runtime: reading a live .NET process or a crash dump from managed code
Microsoft.Diagnostics.Runtime is a set of APIs for introspecting processes and dumps.
At a glance
- What is it?
- ClrMD, the Microsoft.Diagnostics.Runtime package, gives you APIs for introspecting a running .NET process or a crash dump, which is what lets you write your own debugger plugins and analysis tools instead of scripting SOS. It is MIT licensed, published on NuGet, and its interface has changed across the 2.x, 3.x and 4.x major versions.
- Who is it for?
- Adopt ClrMD if you are building a managed diagnostic tool, a debugger extension or an automated analysis pipeline that has to read a live .NET process or a dump, and you want to do it in C# rather than through native debugger extensions. Do not adopt it for a runtime that is not the CLR, since the library reads CLR-specific structures.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What ClrMD is, and what it is a substitute for
Microsoft.Diagnostics.Runtime.dll, also called ClrMD, is a process and crash dump introspection library. The README states plainly what it is for: it allows you to write tools and debugger plugins which can do things similar to SOS and PSSCOR.
That sentence is the whole positioning, and the comparison to SOS is the one to hold on to. SOS and PSSCOR are the reference tools named in the README, and the point of ClrMD is to offer that class of capability to managed code rather than to a debugger session.
ClrMD is a managed library that gives you the same class of capability from C#. You can enumerate the threads, the heap objects, the types, the method tables, the modules and the CLR's own metadata, from a program rather than from a debugger session. The difference in approach is the important one. SOS is an interactive tool for a human; ClrMD is a library for a program, which means it can run unattended, in a test, in a CI job, or inside a debugger plugin that is one tab of a larger tool.
The audience is therefore narrower than the number of people who have used SOS might suggest. It is the developer writing a diagnostic tool, the person building an automated memory analysis pipeline, and the author of a debugger extension who wants the introspection in managed code rather than in a native extension with a hand-written COM interface.
The primary language is C#, the licence is MIT, and the package is published on NuGet as Microsoft.Diagnostics.Runtime, with the README carrying both a version badge and a download count badge for that package.
Two targets, one API: live process and crash dump
The library covers two situations, and they are the two situations a diagnostic tool usually finds itself in.
The first is a live process, where the tool attaches to a running.NET application and reads its state at the moment of the query. The second is a crash dump, where the tool opens a file written after the process died and reads the state as it was at the crash. The README describes the library as a set of APIs for introspecting processes and dumps, and that pairing is the design's real strength.
The reason a single API can serve both is worth thinking about, because it determines how much of your code is reusable. A dump is a snapshot of a process's address space plus the metadata needed to interpret it, and the CLR's own structures live at the same addresses in both cases. So a library that exposes the same object model, a runtime object with a heap and a set of modules, whether it is backed by a live process or a file, means the analysis code does not care which one it has. You write the traversal once and point it at either.
That has a practical consequence for tool design. A tool that can do both is much more useful in a pipeline: you can run it against a live process to see what a slow request is doing, and then run the same tool against the dump from a customer's crash report, without maintaining two code paths that drift apart.
The reverse is also true and worth knowing. Because the library is reading the memory of a process it did not create, it inherits the constraints of that: it needs permission to open the target, it depends on the target's runtime version matching what the library expects, and on a live process the data it reads is only a snapshot, so a concurrent mutation can produce a view that never existed as a consistent state. The README does not discuss the consistency question, so it is worth treating the API as giving you a coherent read of structures rather than a guaranteed atomic snapshot of the whole process.
Where to get the package, and the two distribution channels
The package is on NuGet under Microsoft.Diagnostics.Runtime, which is where most consumers will get it. The README adds a detail that matters if you need the newest build: the latest package is available from the Azure DevOps public feed, at the nuget v3 index URL for the dnceng public dotnet-tools packaging feed, with a browsable link to the same feed.
Two channels for one package is worth understanding. The NuGet version is the stable, published artefact, and it is what a normal project should consume, pinned to a specific version so a rebuild does not silently change behaviour. The Azure DevOps feed carries the latest build, which is what you want when you are developing against a change that has not shipped, or when you need a fix that is in the pipeline but not yet published. The feed is public, so it needs no credentials, but it is also not versioned in the way a released package is, so anything you take from it should be pinned deliberately.
The repository itself shows the rest of the distribution story. There is a NuGet.config at the root, which is how the feed configuration gets into a restore, and Directory.Build.props and Directory.Build.targets, which are where the shared build properties and targets live for the whole solution. Microsoft.Diagnostics.Runtime.sln is the solution, global.json pins the SDK, and there is a build.sh, a restore.sh, a Build.cmd and a Restore.cmd, so the build works from a Unix shell and from Windows.
The pipeline files are worth a note, because the split between them is unusual. There is azure-pipelines-internal.yml and azure-pipelines-external.yml, so there are two separate pipeline definitions, one for internal builds and one for external ones, and both sit at the repository root next to the eng/ directory that holds the build orchestration. The.azuredevops/ directory holds Azure DevOps configuration, and the.github/ directory holds the GitHub-side configuration. The dual pipeline setup is typical of a project that is developed inside a company and consumed publicly, and it is a sign that the internal and external build paths are not the same.
The presence of es-metadata.yml at the root is another Microsoft-specific detail of the repository. It does not affect consumers, but it does explain why the build scripts are as layered as they are.
The documentation set, and the version jumps it documents
The README is short, and it points at a documentation set rather than repeating it. There is a GettingStarted guide, an FAQ, and a Samples directory, all under doc/ and src/ respectively, with the links pointing at./doc/GettingStarted.md,./doc/FAQ.md and./src/Samples.
What is in the doc/ directory at the top level, in the listing, tells you what the documentation covers. There is a guide for getting started, an FAQ document, and the migration guides, which are the most substantive part of the set.
Three migration guides are linked, and their existence is the most important documentation fact about the project. There is Migrating21 for moving from 2.0 to 2.1, Migrating3 for moving from 2.x to 3.x, and Migrating4 for moving from 3.x to 4.0. That is three major-version migrations, each with its own document, which tells you the public API has changed substantially across them.
This is the part to weigh before you commit. A library with a documented migration guide for every major version is a library whose API is not stable across majors. For a diagnostic tool, that matters less than it would for, say, a web framework, because the surface you depend on is narrow: you open a runtime, you enumerate objects, you read fields. But it does mean that when you upgrade, you read a document, and when you pin, you are pinning against a specific set of type shapes and enum values that a later major version will move.
The migration guides also tell you something about the project's maturity. A library that has had three major versions and documented each transition is being maintained rather than abandoned, and the version numbers in the badges are the current published state. The repository has no GitHub releases, so the NuGet package version is the record.
The final document to know about is SECURE-CONFIGURATION.md, which the README links as Secure Configuration Guidelines, alongside SECURITY.md at the repository root for reporting vulnerabilities. For a library whose entire job is reading another process's memory, having a published set of secure configuration guidelines is not a formality. It tells you how the library is meant to be deployed and configured without becoming a way to read the memory of processes the tool was not given access to, and it is the document to read before you wire the library into a service that runs with elevated privileges.
What the repository structure implies about how it is built
The top-level listing describes a repository that follows Microsoft's shared engineering conventions, and reading the directory names tells you where the work happens.
There is eng/ for the engineering scripts, which in the Microsoft dotnet repos is where the build orchestration lives, the version stamping, the CI entry points and the shared targets. Directory.Build.props and Directory.Build.targets sit at the root, so the shared build configuration applies to every project in the solution without repetition. The solution file is Microsoft.Diagnostics.Runtime.sln, and src/ holds the actual library and the Samples directory the README links to, and the test runs are driven from scripts at the repository root.
The test entry points are separate files rather than a Makefile: test.sh, Build.cmd, Restore.cmd and build.sh, which is the pattern the shared engineering tooling expects so that a build can be invoked the same way from a Unix shell and from a Windows command prompt. The.editorconfig,.gitattributes and Directory.Build.props together are how a repository with a large number of contributors keeps formatting and line endings consistent without arguments on every commit.
The one piece of the tree that deserves a specific mention is es-metadata.yml. This file is a Microsoft-specific piece of repository metadata. For a consumer it is invisible. For anyone who has read other Microsoft dotnet repositories, it is a familiar sign that this is a public mirror of an internally developed project.
One structural note about the samples, because it changes how you evaluate the API. The samples live under src/ rather than in a separate top-level examples directory, which in this layout means the sample projects are part of the shipped source tree rather than a separate artifact. That is convenient: the samples are compiled and versioned alongside the library, so they tend not to drift out of date the way a separately maintained example repository does.
Where ClrMD is the wrong tool
There are three limits, and the first is the one that decides the whole evaluation.
ClrMD is CLR-specific. It reads the runtime's internal data structures, the heap layout, the method tables, the metadata and the module list, and those are the structures of the Common Language Runtime. A process that is not a.NET process has none of them, so the library has nothing to offer. The same applies to a native application, or a.NET application running on a runtime whose internal layout the library does not know. If your target population is mixed, this is a per-target decision rather than a general solution.
The second is the version coupling, and it is more specific than the migration guides alone suggest. A library that reads a runtime's internal structures is reading a layout that changes between runtime versions. A process running a newer.NET than the library was built against may present structures the library misinterprets. This is not a hypothetical concern for a library whose subject is the runtime's memory, and it is why the library documents migrations between major versions, and why pinning the package version to the runtime version of your targets is a practical requirement rather than a preference.
The third is the privilege model. Reading another process's memory requires opening that process, which on Windows means a handle with the right access rights, and the tool needs to be running with sufficient privilege to get it. For a diagnostic tool running on a developer machine that is unremarkable. For a diagnostic service deployed across a fleet, it is an architectural commitment: you are building a component whose entire purpose is to read other processes' memory, and the secure configuration guidelines in the repository exist because that is a design decision with consequences.
And a fourth, more practical point. ClrMD is a lower-level tool than the alternatives. If your need is to read a few values out of a live.NET process, a diagnostic IPC channel built for that purpose, or the modern EventPipe and dotnet-counters tooling, is a much smaller commitment than linking a heap-introspection library. ClrMD earns its cost when you need the object graph itself, the types, the fields, the references between objects, and the ability to walk a managed stack frame by frame. That is what a memory forensics tool or a custom debugger view needs, and it is more than most monitoring needs.
Editorial conclusion
Adopt ClrMD if you are building a managed diagnostic tool, a debugger extension or an automated analysis pipeline that has to read a live .NET process or a dump, and you want to do it in C# rather than through native debugger extensions. Do not adopt it for a runtime that is not the CLR, since the library reads CLR-specific structures. Verify first that the package version you pin matches the runtime version of the target you are introspecting, that you have read the migration guide for the major version you are moving to, and that your deployment satisfies the secure configuration guidelines the repository points at, because this library reads another process's memory by design.
Frequently asked questions
What is Microsoft.Diagnostics.Runtime, also called ClrMD?
It is a .NET library for introspecting running processes and crash dumps, and the README says it lets you write tools and debugger plugins that do things similar to SOS and PSSCOR. The package is published on NuGet as Microsoft.Diagnostics.Runtime.
Where can I get the latest build of Microsoft.Diagnostics.Runtime?
The README says the latest package is available from the Azure DevOps public feed at the dnceng dotnet-tools nuget v3 index URL, alongside the NuGet package. The repository also carries a NuGet.config at its root, which is how that feed is configured for a restore.
Has the ClrMD API changed across versions?
Yes. The README links three migration guides: Migrating21 for 2.0 to 2.1, Migrating3 for 2.x to 3.x, and Migrating4 for 3.x to 4.0, all under doc/. A library that documents a migration for every major version has a public API that moves between majors.
Is there security guidance for Microsoft.Diagnostics.Runtime?
The README links SECURE-CONFIGURATION.md as the Secure Configuration Guidelines, and the repository root also carries a SECURITY.md for reporting vulnerabilities. This matters because the library's purpose is reading another process's memory.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/microsoft-clrmd)Was this useful?