Runic.Platform.Runtime 0.11.0

dotnet add package Runic.Platform.Runtime --version 0.11.0
                    
NuGet\Install-Package Runic.Platform.Runtime -Version 0.11.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="Runic.Platform.Runtime" Version="0.11.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Runic.Platform.Runtime" Version="0.11.0" />
                    
Directory.Packages.props
<PackageReference Include="Runic.Platform.Runtime" />
                    
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 Runic.Platform.Runtime --version 0.11.0
                    
#r "nuget: Runic.Platform.Runtime, 0.11.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 Runic.Platform.Runtime@0.11.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=Runic.Platform.Runtime&version=0.11.0
                    
Install as a Cake Addin
#tool nuget:?package=Runic.Platform.Runtime&version=0.11.0
                    
Install as a Cake Tool

Runic.Platform.Runtime

Single instance, requests to open files and URLs, and file transfers for Runic applications, and the contract for native platform providers.

Preview API targeting .NET 10. Native providers are explicitly selected; this package has no Desktop or ASP.NET Core dependency.

The package has two audiences:

The presentation lifetime, the argument checks the providers share and the settings base class are internal to Runic's own providers and hosts.

Provider contract

A host gives each window an INativeWindowOwner: the window's generation, whether it is still available, and InvokeAsync(Action<nint>), which runs a callback on the window's native thread with its handle (an HWND, an NSWindow* or a GtkWindow*). The handle must not escape the callback. Once the window has closed, InvokeAsync throws OwnerClosedException.

A file-dialog provider is an IPickerBackend. NativePickerBackend turns an INativeFilePicker into one: it passes each dialog's filters, initial folder and multiplicity as a NativeFileDialogRequest to INativeFilePicker.SelectAsync(request, cancellationToken), and the initial folder of a directory dialog to INativeDirectoryPicker.SelectDirectoryAsync(initialDirectory, cancellationToken). A picker that cannot show a dialog throws NativeBackendUnavailableException, which the backend reports as Unavailable(BackendUnavailable). A picker that returns more than one selection also returns true from SupportsMultipleSelection; otherwise OpenFilesAsync reports Unavailable(BackendUnavailable) without showing a dialog. A directory picker that implements INativeDirectoryPicker.SelectDirectoriesAsync(initialDirectory, cancellationToken) returns true from SupportsMultipleDirectorySelection, which OpenDirectoriesAsync and the platform.directories.openMultiple capability follow the same way. The request's ShowFilterChoice asks for a filter choice where the dialog has none of its own; a picker reports the filter the user left selected as the first selection's NativeFileSelection.SelectedFilter, and the backend passes it on as PickerResult<T>.Selected.SelectedFilter only when it is one of the request's filters. The backend releases the access of every selection it does not hand to a lease, including after a failure or cancellation, and reports the native error of a failed selection or commit in the Diagnostic of the result.

Single instance and replies to later launches

ApplicationInstance.ClaimAsync makes the first launch of an application the running instance and forwards later launches to it over a Unix domain socket in a directory only the user can use (on Linux, macOS and Windows). By default a later launch hands over its arguments and exits, and the running instance raises IApplicationInstance.Launched.

// In Main(string[] args): the same as ClaimAsync(id, ApplicationLaunch.FromProcess(args)).
var claim = await ApplicationInstance.ClaimAsync("org.example.Manager", args);

An MSIX-packaged application receives a protocol URI or the files of a file-type activation through its activation, not args, so ClaimAsync(id, args) would forward none of them. Pass the launch that DesktopPlatformServices.GetLaunch(args) (Runic.Application.Views.Desktop) or WindowsPlatformProvider.GetLaunch(args) (Runic.Platform.Windows) returns; both are ApplicationLaunch.FromProcess(args) outside a package:

var claim = await ApplicationInstance.ClaimAsync("org.example.Manager", DesktopPlatformServices.GetLaunch(args));

With ApplicationInstanceOptions.ReplyToLaunches, a later launch, such as a command line, also waits for the running instance's reply: messages (output lines or JSON events, as UTF-8 strings of at most 1 MiB) and an exit status. Set it in every process of the application, so whichever process is the running instance answers.

var options = new ApplicationInstanceOptions { ReplyToLaunches = true };
var claim = await ApplicationInstance.ClaimAsync("org.example.Manager", args, options);

// A later launch: print the running instance's messages and exit with its status.
if (claim is PlatformResult<ApplicationInstanceClaim>.Success { Value: ApplicationInstanceClaim.Forwarded { Reply: { } reply } })
{
    await using (reply)
    {
        // Ctrl+C asks the running instance to cancel; its last messages and exit status still arrive.
        Console.CancelKeyPress += (_, e) => { e.Cancel = true; _ = reply.CancelAsync(); };
        await foreach (var line in reply.ReadMessagesAsync()) Console.WriteLine(line);
        return await reply.WaitForExitAsync() is PlatformResult<int>.Success(var code) ? code : 1;
    }
}

// The running instance: launches that wait carry a reply; complete each one.
instance.Launched += (_, launch) => _ = Task.Run(async () =>
{
    if (launch.Reply is not { } reply) { /* Only handed over: raise the window. */ return; }
    await reply.WriteAsync("working");
    await reply.CompleteAsync(reply.Cancelled.IsCancellationRequested ? 130 : 0);
});
  • IApplicationLaunchReply.Cancelled is cancelled when the launching process asks to cancel, disconnects (disposing its reply, or cancelling a read), or when the running instance ends. CancelRequested is cancelled only for the request (IForwardedLaunchReply.CancelAsync, such as on Ctrl+C), and Disconnected only when the reply ends without an exit status; each is cancelled before Cancelled. Pass CancelRequested to work that should outlive the launching process, such as an operation started over an SSH session that drops. Writes after the launching process went away return false.

  • A write waits while the launching process does not read, so large output is not buffered in memory. Pass a token to WriteAsync to bound the wait; a write cancelled that way ends the reply.

  • When the running instance ends or crashes before the exit status, the messages end and WaitForExitAsync reports Failed(IOError).

  • With ApplicationInstanceOptions.ForwardOnly, the process never becomes the running instance: a command line that talks to a running daemon gets ApplicationInstanceClaim.Forwarded, or ApplicationInstanceClaim.NotRunning when no instance runs, and then does the work itself or reports it. It does not listen meanwhile, so a daemon that starts at the same moment does not wait for it. An instance that is starting is waited for, as with a claim.

    var options = new ApplicationInstanceOptions { ReplyToLaunches = true, ForwardOnly = true };
    switch (await ApplicationInstance.ClaimAsync("org.example.Manager", ApplicationLaunch.FromProcess(args), options))
    {
        case PlatformResult<ApplicationInstanceClaim>.Success { Value: ApplicationInstanceClaim.Forwarded { Reply: { } reply } }:
            /* Read the reply as above. */ break;
        case PlatformResult<ApplicationInstanceClaim>.Success { Value: ApplicationInstanceClaim.NotRunning }:
            /* No daemon: run here. */ break;
    }
    
  • An instance claimed without ReplyToLaunches, or by an SDK before 0.8.0-preview.3, refuses launches that wait: the claim fails with ResourceBusy and an ApplicationInstance diagnostic, and the launch is not handled. Launches without ReplyToLaunches keep the one-way protocol and reach any instance.

Opening files and URLs

ApplicationInstance.CreateOpenRequests(options, instance, launch) turns this launch (by default none) and each later launch of instance into IDesktopOpenRequests.Opened requests: the arguments that are URLs with a registered scheme and, with IncludeFiles, existing files. Linux desktop entries (Exec=app %U) and Windows registrations ("app.exe" "%1") pass them that way. The instance's own Launched handlers still receive every launch. See the opening files and URLs design.

File transfers

LocalFileTransfers.Create() is the IDesktopFileTransfers engine every platform uses, and what AddRunicPlatformServices() registers on Runic Desktop. It copies in 1 MiB blocks under hidden temporary names, renames into place with an exclusive rename, and moves by renaming within a file system. A CS-WebUI application can register it itself. See Copy and move and the file transfer design.

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 (8)

Showing the top 5 NuGet packages that depend on Runic.Platform.Runtime:

Package Downloads
Runic.Platform.Windows

The Windows provider of the Runic.Platform services: desktop services, status icon, and the window services of Runic hosts.

Runic.Platform.Linux.Portal

The Linux provider of the Runic.Platform services, built on XDG desktop portals, D-Bus services and freedesktop.org specifications.

Runic.Platform.Linux

The GTK 3 window services (portal parent, GTK dialogs and clipboard) that Runic.Application.Views.Desktop selects on Linux.

Runic.Platform.MacOS

AppKit owned file dialogs, scoped file access, text clipboard, desktop services and privileged actions for Runic on macOS.

Runic.Platform.Linux.Gtk4

The GTK 4 window services (clipboard and XDG portal parent) that Runic.Application.Views.Desktop selects on Linux.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.11.0 2,098 10/25/2026
0.10.0 6,739 10/22/2026
0.9.1 1,033 10/21/2026
0.9.0 250 10/21/2026
0.8.0-preview.6 1,639 10/19/2026
0.8.0-preview.5 463 10/17/2026
0.8.0-preview.4 1,035 10/17/2026
0.8.0-preview.3 913 10/15/2026
0.8.0-preview.2 159 10/15/2026
0.8.0-preview.1 214 10/15/2026
0.7.0-preview.9 611 10/14/2026
0.7.0-preview.8 135 10/12/2026
0.7.0-preview.7 85 10/12/2026
0.7.0-preview.6 1,251 10/9/2026
0.7.0-preview.5 199 10/9/2026
0.7.0-preview.4 109 10/8/2026
0.7.0-preview.3 251 10/8/2026
0.7.0-preview.2 109 10/7/2026
0.7.0-preview.1 597 10/7/2026
0.6.0-preview.1 863 10/5/2026
Loading failed