Avoid using VerifyVersionInfoW in IsCurrentOSVersionGreaterThanOrEqual
Brief description of your issue
As per the comment by @JohnMcPMS in https://github.com/microsoft/winget-cli/discussions/5450#discussioncomment-13173653 and the related discussion, WinGet presently fails to install portable packages on Windows 11 without a dedicated application manifest. Due to the use of VerifyVersionInfoW, the incorrect version of the OS is detected by default.
As per John's comment:
We already do the majority of the work required to replace it in
GetOSVersion, which produces the log line[CORE] OS: Windows.Desktop v10.0.26100.4061.
Steps to reproduce
Creating a PackageManager instance in C# via COM actually works, but creating an instance of the class exposed by the Microsoft.Management.Deployment doesn't. I have attached a project below where you can easily toggle which method is used:
e.g.
var packageManager = new PackageManager(); // not working for all packages below
// var packageManager = CreatePackageManager(); // working for all packages below
When using the CreatePackageManager function, the less package installs correctly and an empty log is produced in %TEMP%\WinGet\defaultState.
When using new PackageManager(), I get the same error as shown above:
Unhandled exception. System.InvalidOperationException: Failed to install package with status NoApplicableInstallers
at ConsoleApp1.Program.Main() in C:\Users\Fots\source\__learning__\ConsoleApp1\Program.cs:line 62
at ConsoleApp1.Program.<Main>()
And with the increased logging level, here are the logs:
WinGetCOM-2025-05-16-15-58-02.179.log
2025-05-16 15:58:02.180 [CORE] Passed in Correlation Vector Json is invalid: ; Error: * Line 1, Column 1
Syntax error: value, object or array expected.
2025-05-16 15:58:02.180 [CORE] WinGet, version [1.10.340], activity [{2D70BBD0-E62A-4D23-90DD-61733D61FF4F}]
2025-05-16 15:58:02.180 [CORE] OS: Windows.Desktop v10.0.26100.4061
2025-05-16 15:58:02.180 [CORE] Command line Args: "C:\Users\Fots\source\__learning__\ConsoleApp1\bin\Debug\net9.0-windows10.0.26100.0\ConsoleApp1.exe"
2025-05-16 15:58:02.180 [CORE] IsCOMCall:1; Caller: %USERPROFILE%\source\__learning__\ConsoleApp1\bin\Debug\net9.0-windows10.0.26100.0\ConsoleApp1.exe
2025-05-16 15:58:02.220 [CORE] Setting action: Get, Type: Secure, Name: admin_settings
2025-05-16 15:58:02.220 [CORE] Admin settings was not found
2025-05-16 15:58:02.222 [CORE] Setting action: Get, Type: Secure, Name: admin_settings
2025-05-16 15:58:02.222 [CORE] Admin settings was not found
2025-05-16 15:58:02.225 [CLI ] Executing command: download
2025-05-16 15:58:02.225 [WORK] Running task: 0x00007FFBC959DC70 [ln 00000001`80000000+22dc70]
2025-05-16 15:58:02.225 [WORK] Setting data item: 35
2025-05-16 15:58:02.225 [WORK] Running task: ReportExecutionStage
2025-05-16 15:58:02.225 [WORK] Running task: 0x00007FFBC95322D0 [ln 00000001`80000000+1c22d0]
2025-05-16 15:58:02.225 [CLI ] Market Filter created with market: AU
2025-05-16 15:58:02.225 [CLI ] Locale Comparator created with Required Locales: [] , Preferred Locales: [en-GB, en-AU] , IsInstalledLocale: 0
2025-05-16 15:58:02.225 [WORK] Checking data item: 26
2025-05-16 15:58:02.225 [WORK] Checking data item: 25
2025-05-16 15:58:02.225 [WORK] Getting data item: 25
2025-05-16 15:58:02.225 [CLI ] Architecture Comparator created with allowed architectures: [X64, X86, Neutral]
2025-05-16 15:58:02.225 [WORK] Getting data item: 5
2025-05-16 15:58:02.225 [CLI ] Starting installer selection.
2025-05-16 15:58:02.225 [CLI ] Installer [X86,portable,Unknown,] not applicable: Current OS is lower than supported MinOSVersion (10.0.18362) for Portable install
2025-05-16 15:58:02.225 [CLI ] Installer [X64,portable,Unknown,] not applicable: Current OS is lower than supported MinOSVersion (10.0.18362) for Portable install
2025-05-16 15:58:02.225 [CLI ] Installer [Arm,portable,Unknown,] not applicable: Current OS is lower than supported MinOSVersion (10.0.18362) for Portable install
2025-05-16 15:58:02.225 [CLI ] Installer [Arm,portable,Unknown,] not applicable: Machine is not compatible with Arm
2025-05-16 15:58:02.225 [CLI ] Installer [Arm64,portable,Unknown,] not applicable: Current OS is lower than supported MinOSVersion (10.0.18362) for Portable install
2025-05-16 15:58:02.225 [CLI ] Installer [Arm64,portable,Unknown,] not applicable: Machine is not compatible with Arm64
2025-05-16 15:58:02.225 [WORK] Setting data item: 7
2025-05-16 15:58:02.225 [WORK] Running task: 0x00007FFBC95A4ED0 [ln 00000001`80000000+234ed0]
2025-05-16 15:58:02.225 [WORK] Getting data item: 7
2025-05-16 15:58:02.225 [CLI ] Terminating context: 0x8a150010 at C:\__w\1\s\external\pkg\src\AppInstallerCLICore\Workflows\InstallFlow.cpp:12d
WinGetCOM-2025-05-16-15-58-01.644.log
2025-05-16 15:58:01.652 [CORE] Settings loaded from settings.json
2025-05-16 15:58:01.653 [CORE] WinGet, version [1.10.340], activity [{BF410C55-070F-478D-B49D-E713BFC73522}]
2025-05-16 15:58:01.654 [CORE] OS: Windows.Desktop v10.0.26100.4061
2025-05-16 15:58:01.654 [CORE] Command line Args: "C:\Users\Fots\source\__learning__\ConsoleApp1\bin\Debug\net9.0-windows10.0.26100.0\ConsoleApp1.exe"
2025-05-16 15:58:01.654 [CORE] IsCOMCall:1; Caller: %USERPROFILE%\source\__learning__\ConsoleApp1\bin\Debug\net9.0-windows10.0.26100.0\ConsoleApp1.exe
2025-05-16 15:58:01.677 [CORE] Started trust validation of msix at: C:\Users\Fots\AppData\Local\Microsoft/WinGet\State\defaultState\Microsoft.PreIndexed.Package\Microsoft.Winget.Source_8wekyb3d8bbwe\source.msix
2025-05-16 15:58:01.762 [CORE] Result for certificate chain validation of Microsoft origin: 0
2025-05-16 15:58:01.810 [CORE] Result for trust info validation of the msix: 0
2025-05-16 15:58:01.865 [CORE] Started trust validation of msix at: C:\Users\Fots\AppData\Local\Microsoft/WinGet\State\defaultState\Microsoft.PreIndexed.Package\Microsoft.Winget.Source_8wekyb3d8bbwe\source.msix
2025-05-16 15:58:01.918 [CORE] Result for certificate chain validation of Microsoft origin: 0
2025-05-16 15:58:01.957 [CORE] Result for trust info validation of the msix: 0
2025-05-16 15:58:02.057 [REPO] Opening database for ImmutableRead at 'C:\Users\Fots\AppData\Local\Temp\WinGet\defaultState\{CAD10D16-52D1-4345-A93F-1F50F4D27E71}'
2025-05-16 15:58:02.057 [SQL ] Opening SQLite connection #1: 'C:\Users\Fots\AppData\Local\Temp\WinGet\defaultState\{CAD10D16-52D1-4345-A93F-1F50F4D27E71}' [1, 40]
2025-05-16 15:58:02.059 [REPO] Opened SQLite Index with version [2.0], last write [2025-05-16 15:07:08.000]
2025-05-16 15:58:02.182 [REPO] Attempting to open pinning database: C:\Users\Fots\AppData\Local\Microsoft/WinGet\State\defaultState\pinning.db
2025-05-16 15:58:02.186 [CLI ] Manifest fields: Name [less], Version [668]
2025-05-16 15:58:02.186 [REPO] Creating new SQLite Index with version [Latest] at ':memory:'
2025-05-16 15:58:02.186 [SQL ] Opening SQLite connection #2: ':memory:' [6, 0]
2025-05-16 15:58:02.218 [CLI ] Leaf command to execute: root:install
So the root cause of the issue is the following error:
Current OS is lower than supported MinOSVersion (10.0.18362) for Portable install
Sadly this error doesn't isn't quite right as I'm on a version of Windows 11 newer than the MinOSVersion mentioned:
~\source\__learning__\ConsoleApp1 via .NET v9.0.300 🎯 net9.0-windows10.0.26100.0 took 3s
🕙 [ 04:01:40 PM ] ❯ Get-ComputerInfo | Select-Object OsName, OsVersion, OsBuildNumber
OsName OsVersion OsBuildNumber
------ --------- -------------
Microsoft Windows 11 Pro 10.0.26100 26100
As per the recommendation from @JohnMcPMS, a simple manifest such as the following works:
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyCompany.MyApp"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 & Windows 11 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>
And referenced as follows in the csproj:
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
Expected behavior
The WinGet COM interface should correctly detect the OS version without the need to use a manifest when installing portable packages.
Actual behavior
A dedicated manifest is required to ensure that portable packages can be installed successfully.
Environment
Windows Package Manager v1.10.390
Windows: Windows.Desktop v10.0.26100.4061
System Architecture: X64
Package: Microsoft.DesktopAppInstaller v1.25.390.0
There is a cycle where:
- Software uses API to detect OS version and change behavior. Some reasonably large percentage of those choices aren't sufficiently future facing.
- New version of OS is released. The not-future-facing decisions cause the software to run poorly/improperly/not at all.
- The API starts lying about OS version so that things keep working.
- Newly written code wants to know the truth; OS adds manifest / new API to get the truth.
- Goto 1
OS version is really a substitute for declaring a set of dependencies on the OS. The original developer should use better (albeit more complex) methods to determine the presence of that support if available. But WinGet needs to have a way for an independent party to declare that dependency and OS version is easily documentable and a single value.
Since VerifyVersionInfoW is deprecated as well, we should use a mechanism that doesn't cause unpredictable behavior changes between manifest and no-manifest.