Windows integration
Windows support includes module factories, messaging, and native views. The transport and MAUI packages target net10.0-windows10.0.19041.0, with a declared minimum OS of Windows 10 build 17763. See the verification record for tested configurations.
Windows adapters use C# to call WinRT, COM, P/Invoke, or other Windows SDKs. Each transport owns a separate adapter-side ChannelService. The existing codecs and binary messenger handle both directions, including reentrant callbacks, independent streams, cancellation and channel ownership. No Kotlin or Swift binding package is needed on Windows. This is an in-process bridge, not an IPC protocol.
The C++ and Rust experiment demonstrates native DLL implementations behind a small shared C# channel adapter. Run ./eng/verify-windows-interop.ps1 to build both DLLs and execute their channel checks on Windows x64. This is separate from MAUI application and MSIX verification. Both examples passed runtime checks on Windows 11 x64 (build 26200) and Windows 10 LTSC 2019 x64 (build 17763.107), using verified CI-built DLLs. The Rust DLL requires vcruntime140.dll; the Windows 10 VM needed an application-local copy before Rust could load. See the example's test record and deployment notes for exact source commits, binary hashes and coverage limits.
Install in an application
Add the published MAUI integration to your .NET 10 Windows MAUI application:
dotnet add package NativeChannels.Maui --version 0.1.0-preview.2NativeChannels and NativeChannels.Core resolve transitively. The Windows bridge is managed C#, so there is no separate NativeChannels.Native.Windows package. Your adapter can call native DLLs through P/Invoke and must include their runtime dependencies. Register modules and view factories as described below. The source-build commands in the next section are for framework development.
Build and verify
On Windows, install the SDK pinned in global.json and its maui-windows workload:
dotnet workload install maui-windows
./eng/verify-windows.ps1The script also recognizes a local SDK at .tools/dotnet/dotnet.exe. It runs the portable tests, packs the three Windows framework packages into artifacts/windows/packages, checks their Windows assemblies and dependencies, and restores the framework sample into a new isolated NuGet cache. It publishes an unpackaged x64 app, runs its verification, captures sample-result.txt, and closes the process it started. An interactive Windows desktop is needed for runtime verification.
Use ./eng/verify-windows.ps1 -BuildOnly for a compile-only check, as the Windows CI job does. Source packages default to 0.1.0-preview.2; -Version overrides the development version. These packages contain Windows assets only and are kept separate from the mobile release feed. Do not publish them as a combined platform release.
Use -Currency -PackOnly to produce framework and Currency inputs for package assembly without publishing or running the apps. Source builds use framework 0.1.0-preview.2 and Currency 1.1.0-alpha.1 on both the Windows and mobile hosts.
To build just the library:
dotnet build src/NativeChannels.Maui -c Release -p:NativeChannelsWindowsOnly=trueNativeChannelsWindowsOnly selects Windows without requiring mobile workloads. Normal Windows-host project evaluation also includes the mobile frameworks. The sample follows Microsoft's unpackaged Windows deployment guidance.
Signed MSIX deployment
Both samples include Windows manifests and icons. Their default deployment remains unpackaged; -Msix builds a signed installer with minimum Windows version 10.0.17763.0. It includes the .NET runtime and uses the Windows App Runtime framework package shipped beside the installer. Self-contained Windows App SDK MSIX activation is unsupported on Windows 10 1809; see Microsoft's deployment limitation. The verifier checks the generated package's signature entry, architecture, minimum OS and runtime dependency, and records installer and dependency SHA-256 hashes alongside the NuGet hashes. The samples also set WindowsAppSdkDeploymentManagerInitialize=false for MSIX because they use no Main/Singleton features, such as push notifications. This follows Microsoft's auto-initializer guidance and avoids unnecessary runtime component installation at startup on older Windows builds. Apps that use those features must initialize the Deployment Manager.
Create a development signing certificate on the build machine, with the publisher used by the samples:
$cert = New-SelfSignedCertificate -Type Custom -Subject 'CN=NativeChannels Development' `
-KeyUsage DigitalSignature -CertStoreLocation Cert:\CurrentUser\My `
-NotAfter (Get-Date).AddDays(7) `
-TextExtension @('2.5.29.37={text}1.3.6.1.5.5.7.3.3', '2.5.29.19={text}')
Export-Certificate -Cert $cert -FilePath ./test-signing.cer
./eng/verify-windows.ps1 -PackageFeed artifacts/packages -Msix -BuildOnly `
-CertificateThumbprint $cert.Thumbprint
./eng/verify-windows.ps1 -PackageFeed artifacts/packages -Msix -BuildOnly -Currency `
-CertificateThumbprint $cert.ThumbprintThe printed MSIX: path identifies each installer. Copy it, its matching architecture's Dependencies/x64/ (or Dependencies/arm64/) files, the public .cer, and eng/verify-windows-msix.ps1 to a test machine. Trust the certificate in that machine's Local Machine Trusted People store using an administrator session. Older Windows 10 builds also need signed-app sideloading enabled. Follow Microsoft's MSIX signing and test deployment guidance. These are temporary development certificates, not Store or production signing.
Run the installation verifier from the signed-in user's ordinary desktop session:
./verify-windows-msix.ps1 -PackagePath ./Currency.Sample_0.1.0.1_x64.msix `
-DependencyPath ./Dependencies/x64/Microsoft.WindowsAppRuntime.1.8.msix `
-OutputDirectory ./currency-msix-resultsIt refuses to replace an existing sample installation, installs the package, activates its app ID, checks the running process's package identity, and reads the result from the package's LocalState. It closes the app and uninstalls its package, including after a runtime failure. Retained evidence includes the OS build, package and dependency hashes, activation identity, result and removal status. The verifier does not explicitly uninstall shared runtime dependencies; Windows may remove unused dependencies when the app is removed. During test-machine cleanup, remove only remaining test-added dependencies, preserving any that were present before testing. The verifier does not change certificate trust or sideloading settings; remove temporary trust and restore any changed settings when testing is complete. If trust is already configured on the build machine, omit -BuildOnly to build and run this installation check in one command.
Register a module
Implement IWindowsChannelModule in Windows-specific source. A module factory must return a fresh instance for each transport. Register installs handlers; Dispose releases SDK listeners and resources. The transport closes its endpoints and disposes modules in reverse registration order, including modules whose registration failed.
#if WINDOWS
sealed class WindowsDeviceModule : IWindowsChannelModule
{
private MethodChannel? _channel;
public void Register(IChannelService channels)
{
_channel = channels.GetMethodChannel("device");
_channel.SetMethodCallHandler((call, _) => call.Method switch
{
"name" => ValueTask.FromResult<object?>(Environment.MachineName),
_ => throw new MethodNotImplementedException(call.Method),
});
}
public void Dispose() => _channel?.Dispose();
}
#endifRegister the factory at startup alongside the other platforms' entry points:
builder.UseNativeChannels(options => options.Modules.Add(
new("example.DeviceModule", "DeviceModule")
{
#if WINDOWS
WindowsFactory = () => new WindowsDeviceModule(),
#endif
}));A registered module without a Windows factory fails during initialization with an actionable error. Use MauiChannelDispatchers.MainThread for handlers that access WinUI. Initialization must not block waiting for calls to the application's endpoint, which becomes available after construction. Module disposal can run off the UI thread; marshal any SDK-specific UI cleanup explicitly.
Embed a WinUI view
On Windows, NativeViewFactoryRegistration.WindowsFactory receives a WindowsViewContext containing the adapter's channels, instance ID, channel name, and decoded creation parameters. Return a WindowsNativeView containing a WinUI UIElement and an optional cleanup action.
options.ViewFactories.Add(new("example.button", "example.ButtonFactory", "ButtonFactory")
{
#if WINDOWS
WindowsFactory = context =>
{
var channel = context.Channels.GetMethodChannel(context.ChannelName,
new() { HandlerDispatcher = MauiChannelDispatchers.MainThread });
var button = new Microsoft.UI.Xaml.Controls.Button { Content = "Native Windows" };
channel.SetMethodCallHandler((call, _) => call.Method == "title"
? ValueTask.FromResult(button.Content)
: throw new MethodNotImplementedException(call.Method));
return new WindowsNativeView(button, channel.Dispose);
},
#endif
});The factory and view cleanup run on the UI thread. Detach invalidates the channel, removes the element, and invokes cleanup once. Reconnect creates a new endpoint, identity, and element. If a factory throws before returning its host, it must release any SDK listeners it already created. The framework sample includes a bidirectional Windows button and reconnect stress checks.
The Currency reference plugin now includes a Windows adapter. Run ./eng/verify-windows.ps1 -Currency to build its Windows-only preview package, execute native API tests, and run the separate app. The PDF, audio and volume adapters also have Windows implementations:
./eng/verify-windows.ps1 -Plugin PdfViewer
./eng/verify-windows.ps1 -Plugin AudioStreamer
./eng/verify-windows.ps1 -Plugin VolumeMonitorThese commands pack the selected plugin and run its native tests and package-only sample. Audio tests send silent PCM through a real output device. The volume test temporarily changes the endpoint level by two percentage points, verifies two independent listeners, and restores the original level. -BuildOnly excludes audio hardware tests; it still runs the PDF renderer and registration/protocol tests. The installed-app verifier recognizes all five samples. Add -Msix -CertificateThumbprint THUMBPRINT when building signed installers, using the certificate setup described above.
-PackageFeed expects combined packages. Add -WindowsOnlyFeed for local Windows-only development archives. -PackageCache PATH explicitly reuses a cache across consumers to save disk space; the default creates a fresh cache. In both cases, restored first-party archives must match the feed hashes. See Windows plugin verification for results and remaining coverage.
Independent Windows CI
Use Verify framework with platforms=Windows. It builds Core once, prepares Windows framework packages once, then compiles the framework sample for x64 and ARM64 in independent jobs. No Android or Apple artifacts are needed. Hosted Windows verification establishes compilation, not desktop execution. See the Windows-only workflow commands.
For separate consumer runs, select package_source=Distribution for a successful distribution run, package_source=Release for a standalone release gate feed, or package_source=Example when using the separate optional example workflow. These feed types are not interchangeable.
Combined platform packages
The manual Verify distribution workflow consumes a successful All / Runtime framework run at the same commit. Its package gate reuses Core, native and Windows artifacts and assembles the combined mobile payloads, then independent consumer jobs verify all seven configurations. The standalone Release / Package gate remains available for packaging-only checks. eng/combine-packages.py combines the transport, MAUI and framework .nupkg and .snupkg files by using --scope framework; the optional example workflow adds one selected plugin with --scope example --plugin NAME. It preserves the mobile native payloads, adds the Windows assemblies and dependency groups, and rejects conflicting versions, commits, metadata, shared files, missing frameworks or symbols. Core and the mobile binding packages retain the mobile build's bytes.
To assemble inputs from the same clean commit manually:
python3 eng/combine-packages.py --mobile artifacts/packages --windows artifacts/windows/packages \
--output artifacts/combined-packages --source-commit FULL_GIT_COMMIT --scope frameworkBoth input feeds must include their symbol packages. The destination must be empty. The script audits the output and records package hashes in package-audit.json. It does not publish or sign packages.
The package-feed artifact contains the combined framework output and sample adapters. Optional plugin builds produce a separate example-package-feed artifact. Separate verification workflows accept its successful run ID and require the exact same source commit. Windows consumers restore the same feed into fresh caches, with archive hash checks and source mapping that requires the local first-party packages. Select one sample and either x64 or ARM64 per run; applicable native API tests execute on the hosted x64 machine.
To verify an optional Currency example feed on an interactive Windows desktop:
./eng/verify-windows.ps1 -PackageFeed artifacts/packages
./eng/verify-windows.ps1 -PackageFeed artifacts/packages -Currency
# Use these options on an ARM64 machine for native runtime verification:
./eng/verify-windows.ps1 -PackageFeed artifacts/packages -RuntimeIdentifier win-arm64
./eng/verify-windows.ps1 -PackageFeed artifacts/packages -RuntimeIdentifier win-arm64 -Currency-PackageFeed consumes existing combined archives without repacking. Add -BuildOnly to cross-compile for the requested architecture. Each successful check writes verification.json with OS, host architecture, target RID, package hashes and whether the result was compilation or execution. An interactive pass also retains the sample result text; the Currency tests retain their TRX report.
For framework releases, verify the framework feed. Verify any example being released separately with its matching optional example feed:
| Host | Required evidence |
|---|---|
| Windows 11 x64 | Native API tests, application lifecycle, and signed installer checks |
| Windows 11 ARM64 | Native ARM64 tests and execution; cross-compilation is insufficient |
| Windows 10 22H2 x64 | Native API tests and separate package-only applications |
| Windows 10 LTSC 2019 x64, minimum build 17763 | Native API tests, applications, and installed MSIX behavior |
| Windows 10 ARM64 | Native ARM64 execution and OS/deployment validation |
CI has compiled the combined feed for x64 and ARM64. Physical Windows 11 x64 checks used Windows-only packages; the broader OS, architecture, and deployment matrix above remains incomplete. Use platform verification and Windows plugin verification to record results. The verifier defaults to unpackaged applications; -Msix selects separate installer verification. Store publication, architecture coverage, and runtime execution must each be reported independently.