WinGet: From Versioned Inputs to Typed Observations
WinGet represents an installed Windows CLI rather than a container-acquired Linux binary. Its Design path handles executable discovery, version normalization, help timeouts and option probes.
The output integration recognizes reviewed exports, selected English/French message shapes and unambiguous package tables while preserving unsupported displays.
Installed-binary acquisition
WindowsBinaryPlan supplies the executable path, process runner, timeout and help/probe callbacks. InstalledBinaryVersionCollector inspects the actual installed version and can compare it with an explicitly requested expected version.
The Design entry point defaults help timeout to 30 seconds and version parallelism to one. It rejects container image/runtime flags because this path does not use container preparation.
WinGetEnvironmentProcessRunner applies declared values to version detection, help and probes. Failed local executions are not marked as proof that a release is unavailable.
Cached help and probes
WinGet help alone does not always establish option value behavior. WinGetOptionProbe collects additional evidence for the parser.
Offline replay consumes cached help/probe data without resolving the executable, detecting a version, running a process or invoking installation callbacks. Exclusive executable locks protect live acquisition; a lock filename alone does not establish ownership.
IncludeParentCommands retains root and meaningful parent invocations. The generated CLR prefix is Winget while the project/environment/event naming uses WinGet.
A complete export example
This offline example uses a generated source-export command and a fixture-shaped compact document. It installs no package and starts no Windows executable.
using FrenchExDev.Net.BinaryWrapper;
using FrenchExDev.Net.BinaryWrapper.Lib;
using FrenchExDev.Net.BinaryWrapper.Testing;
using FrenchExDev.Net.WinGet;
var version = SemanticVersion.Parse("1.29.380");
var binding = new BinaryBinding
{
Identifier = new BinaryIdentifier("winget"),
ExecutablePath = "unused",
DetectedVersion = version,
};
var command = new WingetSourceExportCommand(version);
var line = new OutputLine(
"""{"Name":"winget","Type":"Microsoft.PreIndexed.Package","Arg":"https://example.invalid","Data":"data","Identifier":"id","Explicit":false,"TrustLevel":["Trusted"],"Priority":1}""",
OutputSource.StdOut);
var executor = new CommandExecutor(new DictionaryBinaryResolver(binding),
new FakeProcessRunner([line]));
await foreach (var evt in executor.StreamAsync(
binding.Identifier, command, WinGetOutputStrategies.Default))
{
if (evt is WinGetSourceExportObserved source)
Console.WriteLine($"{source.Name}: {source.Type} {source.Argument}");
if (evt.OutputLine is { } original)
Console.WriteLine($"{original.Source}: {original.Text}");
if (evt is WinGetCommandExited exited)
Console.WriteLine($"Exit: {exited.ExitCode}, HRESULT: 0x{exited.HResult:X8}");
}using FrenchExDev.Net.BinaryWrapper;
using FrenchExDev.Net.BinaryWrapper.Lib;
using FrenchExDev.Net.BinaryWrapper.Testing;
using FrenchExDev.Net.WinGet;
var version = SemanticVersion.Parse("1.29.380");
var binding = new BinaryBinding
{
Identifier = new BinaryIdentifier("winget"),
ExecutablePath = "unused",
DetectedVersion = version,
};
var command = new WingetSourceExportCommand(version);
var line = new OutputLine(
"""{"Name":"winget","Type":"Microsoft.PreIndexed.Package","Arg":"https://example.invalid","Data":"data","Identifier":"id","Explicit":false,"TrustLevel":["Trusted"],"Priority":1}""",
OutputSource.StdOut);
var executor = new CommandExecutor(new DictionaryBinaryResolver(binding),
new FakeProcessRunner([line]));
await foreach (var evt in executor.StreamAsync(
binding.Identifier, command, WinGetOutputStrategies.Default))
{
if (evt is WinGetSourceExportObserved source)
Console.WriteLine($"{source.Name}: {source.Type} {source.Argument}");
if (evt.OutputLine is { } original)
Console.WriteLine($"{original.Source}: {original.Text}");
if (evt is WinGetCommandExited exited)
Console.WriteLine($"Exit: {exited.ExitCode}, HRESULT: 0x{exited.HResult:X8}");
}source export emits source documents on stdout. winget export --output packages.json instead writes package data to a file. The output parser does not open that file or treat its status message as the exported contents.
JSON and human observations
Source/settings exports retain full JSON evidence and project known fields. A settings document's schema identifier is checked before projecting the reviewed shape.
Selected English/French package identity, operation, download, installer hash and HRESULT messages have typed records. Other locales and unknown prose stay raw.
ASCII table parsing relies on unambiguous column boundaries and preserves truncation ellipses. Unicode display-width-sensitive rows are not guessed into package fields. ANSI normalization changes decoded fields while the original logical line is retained.
HRESULT and operation success
Windows process status is a signed 32-bit value. WinGetCommandExited.HResult reinterprets the same bits as unsigned, preserving recognizable hexadecimal HRESULT values.
An observed HRESULT message is content, not automatically the actual process exit. The terminal event is supplied by the runner.
WinGetOutputCollector requires observed zero exit and accounts for known failing HRESULT/hash observations. A “Successfully installed” message does not substitute for terminal success, and arbitrary stderr does not automatically mean failure.
Typed Environment
WinGetEnvironment declares process context variables such as Temp, Tmp, Path, UserProfile, LocalAppData, AppData and SystemRoot. The catalogue's inspected availability baseline is 1.10.340.
These are Windows child-process configuration overrides. They are not invented WINGET_* feature switches and are not package environment declarations.
The shared merge is case-insensitive on Windows. Unset properties preserve inherited values; serializers and process application retain the established null/empty distinctions.
Reviewed profiles
The built-in contracts cover stable patches 1.29.290 and 1.29.380. The profiles use separate names and share a parser because the reviewed emitter contracts agree. Unknown/prerelease versions use raw fallback with actual exit.
Output profiles remain separate from installed help snapshots. A correctly detected executable can have a generated command surface but an unreviewed semantic output contract.
Validation and consumption
Tests exercise source/settings exports, schemas, EN/FR templates, table ambiguity, ANSI retention, HRESULT interpretation, profiles, malformed data, fresh parser instances and generated commands.
Live source/settings queries are distinct read-only checks. Package installation is another operation with separate authorization and acceptance conditions.
These observations describe Windows package sources, settings and operation outcomes. A package-manager milestone remains distinct from installed-package state and actual process exit.
Source snapshot
Source inspection: 2 October 2026. These implementation paths are relative to Net/FrenchExDev in the local ecosystem checkout. The v2 changes are largely uncommitted; these paths identify inspected code, without claiming that public branch links contain it.
WinGet/src/FrenchExDev.Net.WinGet.Design/Program.csWinGet/src/FrenchExDev.Net.WinGet.Contracts/FrenchExDev.Net.WinGet.Contracts.csprojWinGet/src/FrenchExDev.Net.WinGet/FrenchExDev.Net.WinGet.csprojWinGet/doc/TYPED-OUTPUT.mdWinGet/test/FrenchExDev.Net.WinGet.Tests
Previous: Dotnet · Implementation index · Series index · Next: GitLab CI YAML