DesktopHost.Processes 0.3.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package DesktopHost.Processes --version 0.3.0
                    
NuGet\Install-Package DesktopHost.Processes -Version 0.3.0
                    
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="DesktopHost.Processes" Version="0.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DesktopHost.Processes" Version="0.3.0" />
                    
Directory.Packages.props
<PackageReference Include="DesktopHost.Processes" />
                    
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 DesktopHost.Processes --version 0.3.0
                    
#r "nuget: DesktopHost.Processes, 0.3.0"
                    
#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 DesktopHost.Processes@0.3.0
                    
#: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=DesktopHost.Processes&version=0.3.0
                    
Install as a Cake Addin
#tool nuget:?package=DesktopHost.Processes&version=0.3.0
                    
Install as a Cake Tool

desktop-host

.NET building blocks for the local host process of a desktop app — the long-running .NET process that does an app's local work (files, models, devices) next to its window.

Such a process ends up writing the same platform code for itself, and gets it wrong in the same quiet ways:

  • Durable files — a write that survives a crash or a power cut, the brief refusals of virus scanners and sync clients, finding which process holds a file
  • Its own log — a file log that rotates and never fills the disk
  • The processes it starts — workers and helpers that start, report ready, restart within limits and never outlive it

Status: 0.2.0 — DesktopHost.Files, DesktopHost.Logging and DesktopHost.Processes on NuGet. See SCOPE.md for what belongs here.

Packages

DesktopHost.Files

Durable file writes and the reads that go with them.

  • AtomicFile — replace a text file so that a reader sees the whole old or the whole new document, never a part: temp sibling, flush to disk, one atomic rename (a POSIX-semantics rename on Windows), retried for about two seconds through brief locks, with an exception that names who held the file. Shared reads (ReadAllTextShared, ReadLinesShared, and …IfExists forms that answer "absent" only for a missing file) never block such a write.
  • FileRetry — delete or move a file or directory through the seconds a virus scanner or sync client holds it.
  • FileLockHolders — name the processes holding a file open (Windows Restart Manager; empty elsewhere).
  • Trash — move a file or folder to the Recycle Bin (Windows, the shell's own operation with no dialogs) or the freedesktop.org home trash (Linux), so the person can restore it. It never deletes: an item the platform would not keep in its bin — too large, a drive without one — stays where it is and TrashException says why.
using DesktopHost.Files;

// A reader never sees half of this, even while it is being written.
await AtomicFile.WriteAllTextAsync(path, json);

// null only when the file is not there; any other failure throws.
string? text = await AtomicFile.ReadAllTextSharedIfExistsAsync(path);

// Outlasts a scanner holding a just-extracted file.
FileRetry.MoveDirectory(staging, target, logger);

// Restorable from the Recycle Bin; never a permanent delete.
Trash.Move(path);

DesktopHost.Logging

A file log for Microsoft.Extensions.Logging that rotates and never fills the disk.

  • RollingFileLoggerProvider — {prefix}-{yyyy-MM-dd}.log per UTC day, continued in {prefix}-{yyyy-MM-dd}.1.log, .2.log … at a size limit; old files removed by age and by count whenever a file is opened. Lines from any thread come out whole; another process can read the file as it grows; entries after shutdown are dropped rather than thrown.
  • RollingFileLoggerOptions — directory and prefix (required), RetentionPrefix (clear the old files of several writers that share a prefix), RetainedFileTimeLimit (7 days), RetainedFileCountLimit (31), FileSizeLimitBytes (64 MiB), TimeProvider.
using DesktopHost.Logging;

builder.Logging.AddRollingFile(logDirectory, "host");

// Each worker writes its own file; any of them clears the old files of all.
builder.Logging.AddRollingFile(logDirectory, $"worker-{id}", o => o.RetentionPrefix = "worker");

DesktopHost.Processes

Supervision of the long-lived processes a host starts — on top of ChildProcessGuard, which keeps them from outliving the host.

  • ProcessSupervisor — start, wait until ready, start again after an unexpected exit within limits, stop the child's own way before killing its whole tree. A process replaced on request or stopped never triggers a restart; events are raised outside the supervisor's lock, so a handler can call back in.
  • ProcessSupervisorOptions — Command (resolved at each start; the child gets only the environment it names), Ready + ReadyTimeout, RestartPolicy (Delays, StableAfter, IsPermanentExit), StopPolicy (GracefulStop, GracefulTimeout, CloseMainWindow), Guardian (share one per host), Logger, StderrTailLines.
using DesktopHost.Processes;

var env = SupervisedCommand.SafeEnvironment();
env["WORKER_PORT"] = port.ToString();

await using var worker = new ProcessSupervisor(new ProcessSupervisorOptions
{
    Name = "worker",
    Guardian = guardian, // one per host
    Command = () => new SupervisedCommand(workerPath, ["--serve"], env),
    Ready = async (process, ct) => await WaitForHelloAsync(process.StandardOutput, ct),
    Stop = { GracefulStop = (process, ct) => process.StandardInput.WriteLineAsync("quit".AsMemory(), ct) },
});
await worker.StartAsync();

License

MIT — see LICENSE.

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.7.0 114 11/3/2026
0.6.0 107 11/2/2026
0.5.0 182 10/24/2026
0.4.0 104 10/23/2026
0.3.0 134 10/20/2026
0.2.0 150 10/17/2026