MemoryWatcher.Remote 0.0.0-preview.11

This is a prerelease version of MemoryWatcher.Remote.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package MemoryWatcher.Remote --version 0.0.0-preview.11
                    
NuGet\Install-Package MemoryWatcher.Remote -Version 0.0.0-preview.11
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MemoryWatcher.Remote" Version="0.0.0-preview.11" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="MemoryWatcher.Remote" Version="0.0.0-preview.11" />
                    
Directory.Packages.props
<PackageReference Include="MemoryWatcher.Remote" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add MemoryWatcher.Remote --version 0.0.0-preview.11
                    
#r "nuget: MemoryWatcher.Remote, 0.0.0-preview.11"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package MemoryWatcher.Remote@0.0.0-preview.11
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=MemoryWatcher.Remote&version=0.0.0-preview.11&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=MemoryWatcher.Remote&version=0.0.0-preview.11&prerelease
                    
Install as a Cake Tool

MemoryWatcher

.NET C# Platforms Native%20AOT Build Status License

Cross-platform, Native AOT-oriented memory watching toolkit for C# 14 / .NET 10. The repository is built around capability negotiation and honest precision contracts instead of pretending one OS primitive can observe every memory scenario with zero cost and zero loss.

Packages | Internal Projects | Quick Example | Precision Model | Build and Test | Native AOT | Documentation | Public API


Packages

Packable libraries currently produced by this repository:

Package Role Status
MemoryWatcher Managed snapshot/diff engine, planners, interpretation helpers, ring-buffer sink, and polling loop primitives Scaffolded, not published yet
MemoryWatcher.Abstractions Contracts, value types, capability models, watch regions, result types, and observation semantics Scaffolded, not published yet
MemoryWatcher.Unsafe In-process unsafe pointer, bit-region, and typed-value watcher fast paths Scaffolded, not published yet
MemoryWatcher.Native External-process memory sources, resolver helpers, OS-specific watchpoint control, and native capability negotiation Scaffolded, not published yet
MemoryWatcher.Remote Managed session/watch client over the MemoryWatcher.RemoteAot shared-library ABI, packaged with staged win-x64 and linux-x64 native assets for normal NuGet consumption Scaffolded, not published yet

These packages target net10.0 and are intended to stay honest about platform limits rather than flattening them away.

Internal Projects

Non-packable projects that complete the repository:

Project Role
MemoryWatcher.RemoteAot Native AOT shared library exposing a stable external-process C ABI
MemoryWatcher.Agent Native AOT agent shared library for in-process exports and dirty/page-fault-assisted workflows
MemoryWatcher.Sample Minimal runnable example of the managed watcher path
MemoryWatcher.MicroBenchmarks Polling-path performance probes
MemoryWatcher.SmokeTests Executable smoke coverage for core watcher behavior
MemoryWatcher.DocTests Public API snapshot generation for docs/PublicApi.md

What This Repository Actually Supports

Implemented layers include:

  • Managed snapshot watching with a single-bit fast path.
  • Segmented and hash-indexed snapshot watching for larger observed regions.
  • Unsafe in-process pointer and typed-value watchers.
  • Windows ReadProcessMemory + VirtualQueryEx process memory access.
  • Linux process_vm_readv, /proc/<pid>/maps, soft-dirty, and related remote process tracking paths.
  • macOS Mach-based remote reads from an authorized task port.
  • Cooperative dirty-page tracking and agent-fed page-fault-assisted watching.
  • Windows x64/WOW64 and Linux hardware watchpoint controller surfaces.
  • Native AOT shared-library exports for both in-process agent and external-process consumption.
  • Module-relative, absolute, pointer-chain, pattern-scan, and exported-symbol resolver models.
  • Span-based interpretation helpers for bits, integers, floats, and text formats.

Precision Model

The repository is explicit about what it can and cannot guarantee.

  • Polling watchers are single-bit precise between samples. If a bit differs at the next observation, the watcher can report that difference precisely.
  • Polling does not prove transient edges. A 0 -> 1 -> 0 transition that begins and ends between two polls may be missed.
  • Edge-exact observation requires event-backed paths. That means hardware watchpoints or real fault/dirty-page signals where the OS, privileges, and target process model actually support them.
  • Capability reports are intentionally conservative. If a path can miss ABA patterns or depends on per-thread debugger state, the API should admit that instead of hiding it.

See docs/PRECISION.md and docs/BACKENDS.md for the detailed contract.


Quick Example

using MemoryWatcher;

byte[] memory = [0];
using var source = new ManagedMemorySource(memory, MemoryAddress.Zero);
using IBitMemoryWatcher watcher = BitWatcherFactory.CreateSnapshot(
    source,
    BitWatchRegion.SingleBit(MemoryAddress.Zero, 0),
    MemoryWatchOptions.SubMillisecondSnapshot);

Span<BitChange> output = stackalloc BitChange[1];
memory[0] = 1;
BitPollResult result = watcher.Poll(output);

For a runnable sample, see samples/MemoryWatcher.Sample/Program.cs.

External-Process Facade

If you want a friendlier managed API for remote process work, use MemoryWatcher.Native.UnsafeMemoryWatcher:

using MemoryWatcher;
using MemoryWatcher.Native;

using var watcher = new UnsafeMemoryWatcher(new UnsafeMemoryWatcherOptions
{
    ProcessId = targetPid
});

using UnsafeMemoryObservation hp = watcher.Observe(
    UnsafeMemoryRegion.DWord(new MemoryAddress(0x00ABCDEF)),
    UnsafeMemoryObservationPrecision.ByDWord);

Span<UnsafeMemoryUnitChange> units = stackalloc UnsafeMemoryUnitChange[8];
UnsafeMemoryUnitPollResult poll = hp.Poll(units);

If you want a managed client over the shared-library ABI, use MemoryWatcher.Remote.

If you need the language-agnostic shared-library boundary itself, use MemoryWatcher.RemoteAot.

Fastest Polling Path

UnsafeSingleBitWatcher is the lowest-overhead portable polling path in the repository: one byte load, one XOR, one mask test, and an optional event write into caller-owned storage. If missed-edge probability matters, pair it with a dedicated SubMillisecondPollingLoop or run it from a known target hook/tick.

Hardware Watchpoints

This repository exposes hardware watchpoint controllers and related backends, not a fake “universal hardware watcher.”

  • On Windows, use the controller/session surface and consume debugger or in-process exception delivery yourself.
  • On Linux, HardwareWatchpointBackend can combine hardware events with a post-event bit diff through perf_event_open.
  • Thread affinity, privilege requirements, and event delivery semantics remain OS-specific by design.

Build and Test

Build.cs is the repository task runner:

dotnet run Build.cs build Release
dotnet run Build.cs test Release
dotnet run Build.cs -- test -c Release --no-build --no-restore
dotnet run Build.cs bench
dotnet run Build.cs coverage
dotnet run Build.cs pack
dotnet run Build.cs remote-package
dotnet run Build.cs public-api

When forwarding option-style script args such as -c, -o, or --no-build, insert -- after Build.cs.

Native AOT

dotnet publish samples/MemoryWatcher.Sample -c Release -r win-x64 /p:PublishAot=true
dotnet publish samples/MemoryWatcher.Sample -c Release -r linux-x64 /p:PublishAot=true
dotnet publish samples/MemoryWatcher.Sample -c Release -r osx-arm64 /p:PublishAot=true
dotnet pack src/MemoryWatcher.Remote -c Release
dotnet publish src/MemoryWatcher.RemoteAot -c Release -r win-x64
dotnet publish src/MemoryWatcher.RemoteAot -c Release -r linux-x64

dotnet pack src/MemoryWatcher.Remote -c Release produces the managed client package and embeds the MemoryWatcher.RemoteAot native artifact for the selected pack RID. On Windows the default pack RID is win-x64; on Linux it is linux-x64.

To produce the normal cross-host MemoryWatcher.Remote NuGet used by downstream apps, use the one-command release helper:

dotnet run Build.cs -- remote-package Release

On Windows that command stages win-x64 locally and stages linux-x64 through WSL when available. On Linux it stages linux-x64 locally by default. You can override the RID set with --rids, the package output directory with --packages, and the package version with --version-override.

If you also want to push the freshly packed versioned .nupkg files to NuGet, pass an API key:

dotnet run Build.cs -- remote-package Release --api-key <NUGET_KEY> --skip-duplicate

The lower-level manual staging flow is still available when you want explicit control over each step:

pwsh ./eng/publish-remoteaot.ps1 -Rid win-x64
./eng/publish-remoteaot.sh linux-x64
dotnet run Build.cs -- pack Release -p:SkipRemoteAotPublishForPack=true /p:RemoteAotPackRuntimeIdentifiers=win-x64%3Blinux-x64
dotnet run Build.cs -- remote-package-smoke Release --expected-rids win-x64,linux-x64

That flow produces a single MemoryWatcher.Remote package with:

  • runtimes/win-x64/native/MemoryWatcher.RemoteAot.dll
  • runtimes/linux-x64/native/MemoryWatcher.RemoteAot.so

The remote-package-smoke build command restores a temp consumer from the freshly packed NuGet and verifies that NativeMemoryWatchSessionFactory can load the bundled native library and read a self-process memory snapshot.

MemoryWatcher.RemoteAot is the external-process Native AOT shared library. MemoryWatcher.Agent is the in-process agent/export path.

Repository Layout

src/
  MemoryWatcher.Abstractions/   Contracts and value types
  MemoryWatcher.Core/           Managed watcher engine and interpretation
  MemoryWatcher.Unsafe/         Unsafe in-process fast paths
  MemoryWatcher.Native/         OS-specific and remote-process backends
  MemoryWatcher.Remote/         Managed client over the RemoteAot ABI
  MemoryWatcher.RemoteAot/      External-process Native AOT shared library
  MemoryWatcher.Agent/          In-process Native AOT agent shared library
samples/
  MemoryWatcher.Sample/
benchmarks/
  MemoryWatcher.MicroBenchmarks/
tests/
  MemoryWatcher.SmokeTests/
  MemoryWatcher.DocTests/
docs/
  Precision, backend, and ABI documentation

Documentation

Public API

See docs/PublicApi.md for the generated public API reference. It is refreshed by tests/MemoryWatcher.DocTests during the repository test pass.

License

MIT — Copyright (c) 2026 Bia10

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.0-preview.16 61 6/12/2026
0.0.0-preview.13 42 6/11/2026
0.0.0-preview.12 41 6/11/2026
0.0.0-preview.11 36 6/11/2026
0.0.0-preview.10 38 6/11/2026
0.0.0-preview.9 40 6/10/2026
0.0.0-preview.8 47 6/10/2026
0.0.0-preview.6 43 6/10/2026