winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 02454cc355f327109e5ceef8c559125db482fc63
parent 03587c2162d609f4948bbdea20e18769bfd58b29
Author: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date:   Sun,  3 Nov 2024 16:25:25 -0800

Add msstore productId to export manifest and to wingetutil interop manifest object (#4934)

This change was needed as part of the effort to make exported manifest
(from winget download msstore apps) to be re-parsed and uploaded to
winget rest source.
 
Updated the some of the manifest schemas to add "required" for some
required fields previously missing.

Also, during my cross validation with the manifest schemas, I found
ExpectedReturnCode::Custom was added in manifest but not actually
updated in code. So I updated the ExpectedReturnCode map in code with
this change too.
Diffstat:
Mdoc/windows/package-manager/winget/returnCodes.md | 6+++---
Mschemas/JSON/manifests/v1.1.0/manifest.installer.1.1.0.json | 6+++---
Mschemas/JSON/manifests/v1.1.0/manifest.singleton.1.1.0.json | 6+++---
Mschemas/JSON/manifests/v1.2.0/manifest.installer.1.2.0.json | 8++++----
Mschemas/JSON/manifests/v1.2.0/manifest.singleton.1.2.0.json | 6+++---
Mschemas/JSON/manifests/v1.4.0/manifest.installer.1.4.0.json | 6+++---
Mschemas/JSON/manifests/v1.4.0/manifest.singleton.1.4.0.json | 6+++---
Mschemas/JSON/manifests/v1.5.0/manifest.defaultLocale.1.5.0.json | 7++++---
Mschemas/JSON/manifests/v1.5.0/manifest.installer.1.5.0.json | 6+++---
Mschemas/JSON/manifests/v1.5.0/manifest.locale.1.5.0.json | 7++++---
Mschemas/JSON/manifests/v1.5.0/manifest.singleton.1.5.0.json | 10++++++----
Mschemas/JSON/manifests/v1.6.0/manifest.defaultLocale.1.6.0.json | 7++++---
Mschemas/JSON/manifests/v1.6.0/manifest.installer.1.6.0.json | 6+++---
Mschemas/JSON/manifests/v1.6.0/manifest.locale.1.6.0.json | 7++++---
Mschemas/JSON/manifests/v1.6.0/manifest.singleton.1.6.0.json | 10++++++----
Mschemas/JSON/manifests/v1.7.0/manifest.defaultLocale.1.7.0.json | 7++++---
Mschemas/JSON/manifests/v1.7.0/manifest.installer.1.7.0.json | 6+++---
Mschemas/JSON/manifests/v1.7.0/manifest.locale.1.7.0.json | 7++++---
Mschemas/JSON/manifests/v1.7.0/manifest.singleton.1.7.0.json | 10++++++----
Mschemas/JSON/manifests/v1.9.0/manifest.defaultLocale.1.9.0.json | 7++++---
Mschemas/JSON/manifests/v1.9.0/manifest.installer.1.9.0.json | 3++-
Mschemas/JSON/manifests/v1.9.0/manifest.locale.1.9.0.json | 7++++---
Mschemas/JSON/manifests/v1.9.0/manifest.singleton.1.9.0.json | 7+++++--
Msrc/AppInstallerCLICore/Resources.h | 1+
Msrc/AppInstallerCLICore/Workflows/InstallFlow.cpp | 4+++-
Msrc/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw | 9+++++++--
Msrc/AppInstallerCLITests/YamlManifest.cpp | 14++++++++++++++
Msrc/AppInstallerCommonCore/Manifest/ManifestYamlPopulator.cpp | 2++
Msrc/AppInstallerCommonCore/Manifest/YamlWriter.cpp | 135+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/AppInstallerSharedLib/Errors.cpp | 1+
Msrc/AppInstallerSharedLib/Public/AppInstallerErrors.h | 1+
Msrc/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs | 1+
Msrc/WinGetUtilInterop.UnitTests/TestCollateral/V1_9ManifestMerged.yaml | 6+++---
Msrc/WinGetUtilInterop/Manifest/V1/Manifest.cs | 36++++++++++++++++++------------------
Msrc/WinGetUtilInterop/Manifest/V1/ManifestInstaller.cs | 22+++++++++++++++-------
35 files changed, 227 insertions(+), 163 deletions(-)

diff --git a/doc/windows/package-manager/winget/returnCodes.md b/doc/windows/package-manager/winget/returnCodes.md @@ -160,8 +160,7 @@ ms.localizationpriority: medium | 0x8A150107 | -1978334969 | APPINSTALLER_CLI_ERROR_INSTALL_NO_NETWORK | This application requires internet connectivity. Connect to a network then try again. | | 0x8A150108 | -1978334968 | APPINSTALLER_CLI_ERROR_INSTALL_CONTACT_SUPPORT | This application encountered an error during installation. Contact support. | | 0x8A150109 | -1978334967 | APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_FINISH | Restart your PC to finish installation. | -| 0x8A15010A | -1978334966 | APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_INSTALL | -Installation failed. Restart your PC then try again. | +| 0x8A15010A | -1978334966 | APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_REQUIRED_TO_INSTALL | Installation failed. Restart your PC then try again. | | 0x8A15010B | -1978334965 | APPINSTALLER_CLI_ERROR_INSTALL_REBOOT_INITIATED | Your PC will restart to finish installation. | | 0x8A15010C | -1978334964 | APPINSTALLER_CLI_ERROR_INSTALL_CANCELLED_BY_USER | You cancelled the installation. | | 0x8A15010D | -1978334963 | APPINSTALLER_CLI_ERROR_INSTALL_ALREADY_INSTALLED | Another version of this application is already installed. | @@ -171,7 +170,8 @@ Installation failed. Restart your PC then try again. | | 0x8A150111 | -1978334959 | APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE_BY_APPLICATION | Application is currently in use by another application. | | 0x8A150112 | -1978334958 | APPINSTALLER_CLI_ERROR_INSTALL_INVALID_PARAMETER | Invalid parameter. | | 0x8A150113 | -1978334957 | APPINSTALLER_CLI_ERROR_INSTALL_SYSTEM_NOT_SUPPORTED | Package not supported by the system. | -| 0x8A150114 | -1978334956 | APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED | The installer does not support upgrading an existing package. | +| 0x8A150114 | -1978334956 | APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED | The installer does not support upgrading an existing package. | +| 0x8A150115 | -1978334955 | APPINSTALLER_CLI_ERROR_INSTALL_CUSTOM_ERROR | Installation failed with installer custom error. | ## Check for package installed status diff --git a/schemas/JSON/manifests/v1.1.0/manifest.installer.1.1.0.json b/schemas/JSON/manifests/v1.1.0/manifest.installer.1.1.0.json @@ -179,7 +179,8 @@ "blockedByPolicy" ] } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" @@ -667,4 +668,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.1.0/manifest.singleton.1.1.0.json b/schemas/JSON/manifests/v1.1.0/manifest.singleton.1.1.0.json @@ -212,7 +212,8 @@ "blockedByPolicy" ] } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" @@ -803,4 +804,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.2.0/manifest.installer.1.2.0.json b/schemas/JSON/manifests/v1.2.0/manifest.installer.1.2.0.json @@ -200,9 +200,10 @@ }, "ReturnResponseUrl": { "$ref": "#/definitions/Url", - "description": "The return response url to provide additional guidance for expected return codes" + "description": "The return response url to provide additional guidance for expected return codes" } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" @@ -710,4 +711,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.2.0/manifest.singleton.1.2.0.json b/schemas/JSON/manifests/v1.2.0/manifest.singleton.1.2.0.json @@ -244,7 +244,8 @@ "$ref": "#/definitions/Url", "description": "The return response url to provide additional guidance for expected return codes" } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" @@ -872,4 +873,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.4.0/manifest.installer.1.4.0.json b/schemas/JSON/manifests/v1.4.0/manifest.installer.1.4.0.json @@ -246,7 +246,8 @@ "$ref": "#/definitions/Url", "description": "The return response url to provide additional guidance for expected return codes" } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" @@ -831,4 +832,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.4.0/manifest.singleton.1.4.0.json b/schemas/JSON/manifests/v1.4.0/manifest.singleton.1.4.0.json @@ -288,7 +288,8 @@ "$ref": "#/definitions/Url", "description": "The return response url to provide additional guidance for expected return codes" } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" @@ -993,4 +994,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.5.0/manifest.defaultLocale.1.5.0.json b/schemas/JSON/manifests/v1.5.0/manifest.defaultLocale.1.5.0.json @@ -55,7 +55,9 @@ "type": "object", "properties": { "IconUrl": { - "$ref": "#/definitions/Url", + "type": "string", + "pattern": "^([Hh][Tt][Tt][Pp][Ss]?)://.+$", + "maxLength": 2048, "description": "The url of the hosted icon file" }, "IconFileType": { @@ -275,4 +277,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.5.0/manifest.installer.1.5.0.json b/schemas/JSON/manifests/v1.5.0/manifest.installer.1.5.0.json @@ -246,7 +246,8 @@ "$ref": "#/definitions/Url", "description": "The return response url to provide additional guidance for expected return codes" } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" @@ -831,4 +832,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.5.0/manifest.locale.1.5.0.json b/schemas/JSON/manifests/v1.5.0/manifest.locale.1.5.0.json @@ -55,7 +55,9 @@ "type": "object", "properties": { "IconUrl": { - "$ref": "#/definitions/Url", + "type": "string", + "pattern": "^([Hh][Tt][Tt][Pp][Ss]?)://.+$", + "maxLength": 2048, "description": "The url of the hosted icon file" }, "IconFileType": { @@ -266,4 +268,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.5.0/manifest.singleton.1.5.0.json b/schemas/JSON/manifests/v1.5.0/manifest.singleton.1.5.0.json @@ -73,7 +73,9 @@ "type": "object", "properties": { "IconUrl": { - "$ref": "#/definitions/Url", + "type": "string", + "pattern": "^([Hh][Tt][Tt][Pp][Ss]?)://.+$", + "maxLength": 2048, "description": "The url of the hosted icon file" }, "IconFileType": { @@ -346,7 +348,8 @@ "$ref": "#/definitions/Url", "description": "The return response url to provide additional guidance for expected return codes" } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" @@ -1058,4 +1061,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.6.0/manifest.defaultLocale.1.6.0.json b/schemas/JSON/manifests/v1.6.0/manifest.defaultLocale.1.6.0.json @@ -55,7 +55,9 @@ "type": "object", "properties": { "IconUrl": { - "$ref": "#/definitions/Url", + "type": "string", + "pattern": "^([Hh][Tt][Tt][Pp][Ss]?)://.+$", + "maxLength": 2048, "description": "The url of the hosted icon file" }, "IconFileType": { @@ -275,4 +277,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.6.0/manifest.installer.1.6.0.json b/schemas/JSON/manifests/v1.6.0/manifest.installer.1.6.0.json @@ -246,7 +246,8 @@ "$ref": "#/definitions/Url", "description": "The return response url to provide additional guidance for expected return codes" } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" @@ -842,4 +843,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.6.0/manifest.locale.1.6.0.json b/schemas/JSON/manifests/v1.6.0/manifest.locale.1.6.0.json @@ -55,7 +55,9 @@ "type": "object", "properties": { "IconUrl": { - "$ref": "#/definitions/Url", + "type": "string", + "pattern": "^([Hh][Tt][Tt][Pp][Ss]?)://.+$", + "maxLength": 2048, "description": "The url of the hosted icon file" }, "IconFileType": { @@ -266,4 +268,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.6.0/manifest.singleton.1.6.0.json b/schemas/JSON/manifests/v1.6.0/manifest.singleton.1.6.0.json @@ -73,7 +73,9 @@ "type": "object", "properties": { "IconUrl": { - "$ref": "#/definitions/Url", + "type": "string", + "pattern": "^([Hh][Tt][Tt][Pp][Ss]?)://.+$", + "maxLength": 2048, "description": "The url of the hosted icon file" }, "IconFileType": { @@ -346,7 +348,8 @@ "$ref": "#/definitions/Url", "description": "The return response url to provide additional guidance for expected return codes" } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" @@ -1069,4 +1072,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.7.0/manifest.defaultLocale.1.7.0.json b/schemas/JSON/manifests/v1.7.0/manifest.defaultLocale.1.7.0.json @@ -55,7 +55,9 @@ "type": "object", "properties": { "IconUrl": { - "$ref": "#/definitions/Url", + "type": "string", + "pattern": "^([Hh][Tt][Tt][Pp][Ss]?)://.+$", + "maxLength": 2048, "description": "The url of the hosted icon file" }, "IconFileType": { @@ -275,4 +277,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.7.0/manifest.installer.1.7.0.json b/schemas/JSON/manifests/v1.7.0/manifest.installer.1.7.0.json @@ -252,7 +252,8 @@ "$ref": "#/definitions/Url", "description": "The return response url to provide additional guidance for expected return codes" } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" @@ -863,4 +864,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.7.0/manifest.locale.1.7.0.json b/schemas/JSON/manifests/v1.7.0/manifest.locale.1.7.0.json @@ -55,7 +55,9 @@ "type": "object", "properties": { "IconUrl": { - "$ref": "#/definitions/Url", + "type": "string", + "pattern": "^([Hh][Tt][Tt][Pp][Ss]?)://.+$", + "maxLength": 2048, "description": "The url of the hosted icon file" }, "IconFileType": { @@ -266,4 +268,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.7.0/manifest.singleton.1.7.0.json b/schemas/JSON/manifests/v1.7.0/manifest.singleton.1.7.0.json @@ -73,7 +73,9 @@ "type": "object", "properties": { "IconUrl": { - "$ref": "#/definitions/Url", + "type": "string", + "pattern": "^([Hh][Tt][Tt][Pp][Ss]?)://.+$", + "maxLength": 2048, "description": "The url of the hosted icon file" }, "IconFileType": { @@ -352,7 +354,8 @@ "$ref": "#/definitions/Url", "description": "The return response url to provide additional guidance for expected return codes" } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" @@ -1090,4 +1093,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.9.0/manifest.defaultLocale.1.9.0.json b/schemas/JSON/manifests/v1.9.0/manifest.defaultLocale.1.9.0.json @@ -55,7 +55,9 @@ "type": "object", "properties": { "IconUrl": { - "$ref": "#/definitions/Url", + "type": "string", + "pattern": "^([Hh][Tt][Tt][Pp][Ss]?)://.+$", + "maxLength": 2048, "description": "The url of the hosted icon file" }, "IconFileType": { @@ -275,4 +277,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.9.0/manifest.installer.1.9.0.json b/schemas/JSON/manifests/v1.9.0/manifest.installer.1.9.0.json @@ -252,7 +252,8 @@ "$ref": "#/definitions/Url", "description": "The return response url to provide additional guidance for expected return codes" } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" diff --git a/schemas/JSON/manifests/v1.9.0/manifest.locale.1.9.0.json b/schemas/JSON/manifests/v1.9.0/manifest.locale.1.9.0.json @@ -55,7 +55,9 @@ "type": "object", "properties": { "IconUrl": { - "$ref": "#/definitions/Url", + "type": "string", + "pattern": "^([Hh][Tt][Tt][Pp][Ss]?)://.+$", + "maxLength": 2048, "description": "The url of the hosted icon file" }, "IconFileType": { @@ -266,4 +268,4 @@ "ManifestType", "ManifestVersion" ] -}- \ No newline at end of file +} diff --git a/schemas/JSON/manifests/v1.9.0/manifest.singleton.1.9.0.json b/schemas/JSON/manifests/v1.9.0/manifest.singleton.1.9.0.json @@ -73,7 +73,9 @@ "type": "object", "properties": { "IconUrl": { - "$ref": "#/definitions/Url", + "type": "string", + "pattern": "^([Hh][Tt][Tt][Pp][Ss]?)://.+$", + "maxLength": 2048, "description": "The url of the hosted icon file" }, "IconFileType": { @@ -352,7 +354,8 @@ "$ref": "#/definitions/Url", "description": "The return response url to provide additional guidance for expected return codes" } - } + }, + "required": [ "InstallerReturnCode", "ReturnResponse" ] }, "maxItems": 128, "description": "Installer exit codes for common errors" diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h @@ -325,6 +325,7 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(InstallFlowReturnCodeBlockedByPolicy); WINGET_DEFINE_RESOURCE_STRINGID(InstallFlowReturnCodeCancelledByUser); WINGET_DEFINE_RESOURCE_STRINGID(InstallFlowReturnCodeContactSupport); + WINGET_DEFINE_RESOURCE_STRINGID(InstallFlowReturnCodeCustomError); WINGET_DEFINE_RESOURCE_STRINGID(InstallFlowReturnCodeDiskFull); WINGET_DEFINE_RESOURCE_STRINGID(InstallFlowReturnCodeDowngrade); WINGET_DEFINE_RESOURCE_STRINGID(InstallFlowReturnCodeFileInUse); diff --git a/src/AppInstallerCLICore/Workflows/InstallFlow.cpp b/src/AppInstallerCLICore/Workflows/InstallFlow.cpp @@ -145,6 +145,8 @@ namespace AppInstaller::CLI::Workflow return ExpectedReturnCode(returnCode, APPINSTALLER_CLI_ERROR_INSTALL_BLOCKED_BY_POLICY, Resource::String::InstallFlowReturnCodeBlockedByPolicy); case ExpectedReturnCodeEnum::SystemNotSupported: return ExpectedReturnCode(returnCode, APPINSTALLER_CLI_ERROR_INSTALL_SYSTEM_NOT_SUPPORTED, Resource::String::InstallFlowReturnCodeSystemNotSupported); + case ExpectedReturnCodeEnum::Custom: + return ExpectedReturnCode(returnCode, APPINSTALLER_CLI_ERROR_INSTALL_CUSTOM_ERROR, Resource::String::InstallFlowReturnCodeCustomError); default: THROW_HR(E_UNEXPECTED); } @@ -501,7 +503,7 @@ namespace AppInstaller::CLI::Workflow if (FAILED(terminationHR)) { context.Reporter.Error() << returnCode.Message << std::endl; - auto returnResponseUrl = expectedReturnCodeItr->second.ReturnResponseUrl; + const auto& returnResponseUrl = expectedReturnCodeItr->second.ReturnResponseUrl; if (!returnResponseUrl.empty()) { context.Reporter.Error() << Resource::String::RelatedLink << ' ' << returnResponseUrl << std::endl; diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -1284,6 +1284,9 @@ Do you agree to the terms?</value> <data name="InstallFlowReturnCodeSystemNotSupported" xml:space="preserve"> <value>The current system configuration does not support the installation of this package.</value> </data> + <data name="InstallFlowReturnCodeCustomError" xml:space="preserve"> + <value>Installation failed with a custom installer error. Contact package support.</value> + </data> <data name="InstallAbandoned" xml:space="preserve"> <value>Installation abandoned</value> </data> @@ -2521,6 +2524,9 @@ Please specify one of them using the --source option to proceed.</value> <data name="APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED" xml:space="preserve"> <value>The installer does not support upgrading an existing package.</value> </data> + <data name="APPINSTALLER_CLI_ERROR_INSTALL_CUSTOM_ERROR" xml:space="preserve"> + <value>Installation failed with a custom installer error.</value> + </data> <data name="WINGET_INSTALLED_STATUS_ARP_ENTRY_NOT_FOUND" xml:space="preserve"> <value>The Apps and Features Entry for the package could not be found.</value> </data> @@ -3174,4 +3180,4 @@ Please specify one of them using the --source option to proceed.</value> <data name="FontVersion" xml:space="preserve"> <value>Version</value> </data> -</root>- \ No newline at end of file +</root> diff --git a/src/AppInstallerCLITests/YamlManifest.cpp b/src/AppInstallerCLITests/YamlManifest.cpp @@ -1373,6 +1373,20 @@ TEST_CASE("WriteManifestWithMultipleLocale", "[ManifestCreation]") REQUIRE(generatedManifest.Localizations.size() == 2); } +TEST_CASE("WriteManifestWithMSStoreInstaller", "[ManifestCreation]") +{ + Manifest msstoreManifest = YamlParser::CreateFromPath(TestDataFile("DownloadFlowTest_MSStore.yaml")); + TempDirectory exportedDirectory{ "exported" }; + std::filesystem::path generatedManifestPath = exportedDirectory.GetPath() / "testManifestWithMultipleLocale.yaml"; + msstoreManifest.ManifestVersion = ManifestVer{ "1.1.0" }; + YamlWriter::OutputYamlFile(msstoreManifest, msstoreManifest.Installers[0], generatedManifestPath); + + REQUIRE(std::filesystem::exists(generatedManifestPath)); + Manifest generatedManifest = YamlParser::CreateFromPath(generatedManifestPath); + REQUIRE(generatedManifest.Installers[0].BaseInstallerType == InstallerTypeEnum::MSStore); + REQUIRE(!generatedManifest.Installers[0].ProductId.empty()); +} + YamlManifestInfo CreateYamlManifestInfo(std::string testDataFile) { YamlManifestInfo result; diff --git a/src/AppInstallerCommonCore/Manifest/ManifestYamlPopulator.cpp b/src/AppInstallerCommonCore/Manifest/ManifestYamlPopulator.cpp @@ -310,6 +310,8 @@ namespace AppInstaller::Manifest { "InstallerUrl", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->Url = value.as<std::string>(); return {}; } }, { "InstallerSha256", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->Sha256 = Utility::SHA256::ConvertToBytes(value.as<std::string>()); return {}; } }, { "SignatureSha256", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->SignatureSha256 = Utility::SHA256::ConvertToBytes(value.as<std::string>()); return {}; } }, + // No custom validation needed at field populating time since we have semantic validation later to block msstore and productId from community repo. + { "MSStoreProductIdentifier", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr<ManifestInstaller>(v)->ProductId = value.as<std::string>(); return {}; } }, }; std::move(v1InstallerFields.begin(), v1InstallerFields.end(), std::inserter(result, result.end())); diff --git a/src/AppInstallerCommonCore/Manifest/YamlWriter.cpp b/src/AppInstallerCommonCore/Manifest/YamlWriter.cpp @@ -150,6 +150,22 @@ namespace AppInstaller::Manifest::YamlWriter { \ WRITE_PROPERTY(emitter, key, value) \ } \ + } + +#define WRITE_SHA256_PROPERTY_IF_NOT_EMPTY(emitter, key, field) \ + { \ + if (!field.empty()) \ + { \ + WRITE_PROPERTY(emitter, key, Utility::SHA256::ConvertToString(field)) \ + } \ + } + +#define WRITE_ENUM_PROPERTY_IF_NOT_UNKNOWN(emitter, key, value, enumField, enumType) \ + { \ + if (enumField != enumType::Unknown) \ + { \ + WRITE_PROPERTY(emitter, key, value) \ + } \ } void ProcessAgreements(YAML::Emitter& out, const std::vector<AppInstaller::Manifest::Agreement>& agreements) @@ -203,18 +219,18 @@ namespace AppInstaller::Manifest::YamlWriter for (const auto& icon : icons) { out << YAML::BeginMap; - WRITE_PROPERTY_IF_EXISTS(out, IconUrl, icon.Url); - WRITE_PROPERTY_IF_EXISTS(out, IconFileType, IconFileTypeToString(icon.FileType)); - WRITE_PROPERTY_IF_EXISTS(out, IconResolution, IconResolutionToString(icon.Resolution)); - WRITE_PROPERTY_IF_EXISTS(out, IconTheme, IconThemeToString(icon.Theme)); - WRITE_PROPERTY_IF_EXISTS(out, IconSha256, Utility::LocIndString{ Utility::SHA256::ConvertToString(icon.Sha256)}); + WRITE_PROPERTY(out, IconUrl, icon.Url); + WRITE_PROPERTY(out, IconFileType, IconFileTypeToString(icon.FileType)); + WRITE_ENUM_PROPERTY_IF_NOT_UNKNOWN(out, IconResolution, IconResolutionToString(icon.Resolution), icon.Resolution, IconResolutionEnum); + WRITE_ENUM_PROPERTY_IF_NOT_UNKNOWN(out, IconTheme, IconThemeToString(icon.Theme), icon.Theme, IconThemeEnum); + WRITE_SHA256_PROPERTY_IF_NOT_EMPTY(out, IconSha256, icon.Sha256); out << YAML::EndMap; } out << YAML::EndSeq; } // Generic method for handling a list of strings (i.e. tags) - void ProcessSequence(YAML::Emitter& out, std::string_view name, std::vector<AppInstaller::Manifest::string_t> items) + void ProcessStringSequence(YAML::Emitter& out, std::string_view name, std::vector<AppInstaller::Manifest::string_t> items) { if (items.empty()) { @@ -224,8 +240,11 @@ namespace AppInstaller::Manifest::YamlWriter out << YAML::Key << name; out << YAML::BeginSeq; for (const auto& item : items) - { - out << item; + { + if (!item.empty()) + { + out << item; + } } out << YAML::EndSeq; } @@ -235,7 +254,7 @@ namespace AppInstaller::Manifest::YamlWriter ProcessAgreements(out, manifest.Get<Localization::Agreements>()); ProcessDocumentations(out, manifest.Get<Localization::Documentations>()); ProcessIcons(out, manifest.Get<Localization::Icons>()); - ProcessSequence(out, Tags, manifest.Get<Localization::Tags>()); + ProcessStringSequence(out, Tags, manifest.Get<Localization::Tags>()); WRITE_PROPERTY(out, PackageLocale, manifest.Locale); WRITE_PROPERTY_IF_EXISTS(out, Author, manifest.Get<Localization::Author>()); @@ -271,12 +290,7 @@ namespace AppInstaller::Manifest::YamlWriter out << YAML::BeginMap; WRITE_PROPERTY_IF_EXISTS(out, DisplayName, appsAndFeatureEntry.DisplayName); WRITE_PROPERTY_IF_EXISTS(out, DisplayVersion, appsAndFeatureEntry.DisplayVersion); - - if (appsAndFeatureEntry.InstallerType != InstallerTypeEnum::Unknown) - { - WRITE_PROPERTY(out, InstallerType, InstallerTypeToString(appsAndFeatureEntry.InstallerType)); - } - + WRITE_ENUM_PROPERTY_IF_NOT_UNKNOWN(out, InstallerType, InstallerTypeToString(appsAndFeatureEntry.InstallerType), appsAndFeatureEntry.InstallerType, InstallerTypeEnum); WRITE_PROPERTY_IF_EXISTS(out, ProductCode, appsAndFeatureEntry.ProductCode); WRITE_PROPERTY_IF_EXISTS(out, Publisher, appsAndFeatureEntry.Publisher); WRITE_PROPERTY_IF_EXISTS(out, UpgradeCode, appsAndFeatureEntry.UpgradeCode); @@ -313,8 +327,8 @@ namespace AppInstaller::Manifest::YamlWriter for (const auto& expectedReturnCode : expectedReturnCodes) { out << YAML::BeginMap; - WRITE_PROPERTY_IF_EXISTS(out, InstallerReturnCode, std::to_string(expectedReturnCode.first)); - WRITE_PROPERTY_IF_EXISTS(out, ReturnResponse, ExpectedReturnCodeToString(expectedReturnCode.second.ReturnResponseEnum)); + WRITE_PROPERTY(out, InstallerReturnCode, std::to_string(expectedReturnCode.first)); + WRITE_PROPERTY(out, ReturnResponse, ExpectedReturnCodeToString(expectedReturnCode.second.ReturnResponseEnum)); WRITE_PROPERTY_IF_EXISTS(out, ReturnResponseUrl, expectedReturnCode.second.ReturnResponseUrl); out << YAML::EndMap; } @@ -330,9 +344,12 @@ namespace AppInstaller::Manifest::YamlWriter out << YAML::Key << UnsupportedArguments; out << YAML::BeginSeq; - for (auto const& unsupportedArgs : unsupportedArguments) + for (auto const& unsupportedArg : unsupportedArguments) { - out << UnsupportedArgumentToString(unsupportedArgs); + if (unsupportedArg != UnsupportedArgumentEnum::Unknown) + { + out << UnsupportedArgumentToString(unsupportedArg); + } } out << YAML::EndSeq; } @@ -347,8 +364,11 @@ namespace AppInstaller::Manifest::YamlWriter out << YAML::Key << UnsupportedOSArchitectures; out << YAML::BeginSeq; for (auto const& architecture : architectures) - { - out << Utility::ToLower(ToString(architecture)); + { + if (architecture != AppInstaller::Utility::Architecture::Unknown) + { + out << Utility::ToLower(ToString(architecture)); + } } out << YAML::EndSeq; } @@ -363,8 +383,11 @@ namespace AppInstaller::Manifest::YamlWriter out << YAML::Key << InstallModes; out << YAML::BeginSeq; for (auto const& installMode : installModes) - { - out << InstallModeToString(installMode); + { + if (installMode != InstallModeEnum::Unknown) + { + out << InstallModeToString(installMode); + } } out << YAML::EndSeq; } @@ -378,8 +401,11 @@ namespace AppInstaller::Manifest::YamlWriter out << YAML::Key << Platform; out << YAML::BeginSeq; for (auto const& platform : platforms) - { - out << PlatformToString(platform); + { + if (platform != PlatformEnum::Unknown) + { + out << PlatformToString(platform); + } } out << YAML::EndSeq; } @@ -409,8 +435,8 @@ namespace AppInstaller::Manifest::YamlWriter out << YAML::Key << Markets; out << YAML::BeginMap; - ProcessSequence(out, AllowedMarkets, marketsInfo.AllowedMarkets); - ProcessSequence(out, ExcludedMarkets, marketsInfo.ExcludedMarkets); + ProcessStringSequence(out, AllowedMarkets, marketsInfo.AllowedMarkets); + ProcessStringSequence(out, ExcludedMarkets, marketsInfo.ExcludedMarkets); out << YAML::EndMap; } @@ -426,7 +452,7 @@ namespace AppInstaller::Manifest::YamlWriter for (const auto& nestedInstallerFile : nestedInstallerFiles) { out << YAML::BeginMap; - WRITE_PROPERTY_IF_EXISTS(out, NestedInstallerFileRelativeFilePath, nestedInstallerFile.RelativeFilePath); + WRITE_PROPERTY(out, NestedInstallerFileRelativeFilePath, nestedInstallerFile.RelativeFilePath); WRITE_PROPERTY_IF_EXISTS(out, PortableCommandAlias, nestedInstallerFile.PortableCommandAlias); out << YAML::EndMap; } @@ -445,9 +471,9 @@ namespace AppInstaller::Manifest::YamlWriter for (const auto& installedFile : installedFiles) { out << YAML::BeginMap; - WRITE_PROPERTY_IF_EXISTS(out, InstallationMetadataRelativeFilePath, installedFile.RelativeFilePath); - WRITE_PROPERTY_IF_EXISTS(out, FileSha256, Utility::LocIndString{ Utility::SHA256::ConvertToString(installedFile.FileSha256) }); - WRITE_PROPERTY_IF_EXISTS(out, FileType, InstalledFileTypeToString(installedFile.FileType)); + WRITE_PROPERTY(out, InstallationMetadataRelativeFilePath, installedFile.RelativeFilePath); + WRITE_SHA256_PROPERTY_IF_NOT_EMPTY(out, FileSha256, installedFile.FileSha256); + WRITE_ENUM_PROPERTY_IF_NOT_UNKNOWN(out, FileType, InstalledFileTypeToString(installedFile.FileType), installedFile.FileType, InstalledFileTypeEnum); WRITE_PROPERTY_IF_EXISTS(out, InvocationParameter, installedFile.InvocationParameter); WRITE_PROPERTY_IF_EXISTS(out, DisplayName, installedFile.DisplayName); @@ -509,7 +535,7 @@ namespace AppInstaller::Manifest::YamlWriter dependencies.ApplyToType(DependencyType::Package, [&out](Dependency dependency) { out << YAML::BeginMap; - WRITE_PROPERTY_IF_EXISTS(out, PackageIdentifier, dependency.Id()); + WRITE_PROPERTY(out, PackageIdentifier, dependency.Id()); if (dependency.MinVersion.has_value()) { @@ -539,30 +565,15 @@ namespace AppInstaller::Manifest::YamlWriter { WRITE_PROPERTY(out, Architecture, Utility::ToLower(ToString(installer.Arch))); WRITE_PROPERTY(out, InstallerType, InstallerTypeToString(installer.BaseInstallerType)); + WRITE_ENUM_PROPERTY_IF_NOT_UNKNOWN(out, NestedInstallerType, InstallerTypeToString(installer.NestedInstallerType), installer.NestedInstallerType, InstallerTypeEnum); + WRITE_SHA256_PROPERTY_IF_NOT_EMPTY(out, InstallerSha256, installer.Sha256); + WRITE_SHA256_PROPERTY_IF_NOT_EMPTY(out, SignatureSha256, installer.SignatureSha256); + WRITE_PROPERTY_IF_EXISTS(out, InstallerUrl, installer.Url); + WRITE_PROPERTY_IF_EXISTS(out, MSStoreProductIdentifier, installer.ProductId); - if (installer.NestedInstallerType != InstallerTypeEnum::Unknown) - { - WRITE_PROPERTY(out, NestedInstallerType, InstallerTypeToString(installer.NestedInstallerType)); - } - - if (!installer.Sha256.empty()) - { - WRITE_PROPERTY(out, InstallerSha256, Utility::SHA256::ConvertToString(installer.Sha256)); - } - - if (!installer.SignatureSha256.empty()) - { - WRITE_PROPERTY(out, SignatureSha256, Utility::SHA256::ConvertToString(installer.SignatureSha256)); - } - WRITE_PROPERTY_IF_EXISTS(out, InstallerUrl, installer.Url); - WRITE_PROPERTY_IF_EXISTS(out, Scope, Utility::ToLower(ScopeToString(installer.Scope))); + WRITE_ENUM_PROPERTY_IF_NOT_UNKNOWN(out, Scope, Utility::ToLower(ScopeToString(installer.Scope)), installer.Scope, ScopeEnum); WRITE_PROPERTY_IF_EXISTS(out, InstallerLocale, installer.Locale); - - if (installer.ElevationRequirement != ElevationRequirementEnum::Unknown) - { - WRITE_PROPERTY(out, ElevationRequirement, ElevationRequirementToString(installer.ElevationRequirement)); - } - + WRITE_ENUM_PROPERTY_IF_NOT_UNKNOWN(out, ElevationRequirement, ElevationRequirementToString(installer.ElevationRequirement), installer.ElevationRequirement, ElevationRequirementEnum); WRITE_PROPERTY_IF_EXISTS(out, PackageFamilyName, installer.PackageFamilyName); WRITE_PROPERTY_IF_EXISTS(out, ReleaseDate, installer.ReleaseDate); WRITE_BOOL_PROPERTY(out, InstallerAbortsTerminal, installer.InstallerAbortsTerminal); @@ -573,14 +584,14 @@ namespace AppInstaller::Manifest::YamlWriter WRITE_BOOL_PROPERTY(out, ArchiveBinariesDependOnPath, installer.ArchiveBinariesDependOnPath); WRITE_PROPERTY_IF_EXISTS(out, MinimumOSVersion, installer.MinOSVersion); WRITE_PROPERTY_IF_EXISTS(out, ProductCode, installer.ProductCode); - WRITE_PROPERTY_IF_EXISTS(out, UpgradeBehavior, UpdateBehaviorToString(installer.UpdateBehavior)); - WRITE_PROPERTY_IF_EXISTS(out, RepairBehavior, RepairBehaviorToString(installer.RepairBehavior)); - - ProcessSequence(out, Capabilities, installer.Capabilities); - ProcessSequence(out, Commands, installer.Commands); - ProcessSequence(out, FileExtensions, installer.FileExtensions); - ProcessSequence(out, Protocols, installer.Protocols); - ProcessSequence(out, RestrictedCapabilities, installer.RestrictedCapabilities); + WRITE_ENUM_PROPERTY_IF_NOT_UNKNOWN(out, UpgradeBehavior, UpdateBehaviorToString(installer.UpdateBehavior), installer.UpdateBehavior, UpdateBehaviorEnum); + WRITE_ENUM_PROPERTY_IF_NOT_UNKNOWN(out, RepairBehavior, RepairBehaviorToString(installer.RepairBehavior), installer.RepairBehavior, RepairBehaviorEnum); + + ProcessStringSequence(out, Capabilities, installer.Capabilities); + ProcessStringSequence(out, Commands, installer.Commands); + ProcessStringSequence(out, FileExtensions, installer.FileExtensions); + ProcessStringSequence(out, Protocols, installer.Protocols); + ProcessStringSequence(out, RestrictedCapabilities, installer.RestrictedCapabilities); ProcessAppsAndFeaturesEntries(out, installer.AppsAndFeaturesEntries); ProcessDependencies(out, installer.Dependencies); diff --git a/src/AppInstallerSharedLib/Errors.cpp b/src/AppInstallerSharedLib/Errors.cpp @@ -244,6 +244,7 @@ namespace AppInstaller WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_INVALID_PARAMETER, "Invalid parameter."), WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_SYSTEM_NOT_SUPPORTED, "Package not supported by the system."), WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED, "The installer does not support upgrading an existing package."), + WINGET_HRESULT_INFO(APPINSTALLER_CLI_ERROR_INSTALL_CUSTOM_ERROR, "Installation failed with a custom installer error."), // Status values for check package installed status results. // Partial success has the success bit(first bit) set to 0. diff --git a/src/AppInstallerSharedLib/Public/AppInstallerErrors.h b/src/AppInstallerSharedLib/Public/AppInstallerErrors.h @@ -174,6 +174,7 @@ #define APPINSTALLER_CLI_ERROR_INSTALL_INVALID_PARAMETER ((HRESULT)0x8A150112) #define APPINSTALLER_CLI_ERROR_INSTALL_SYSTEM_NOT_SUPPORTED ((HRESULT)0x8A150113) #define APPINSTALLER_CLI_ERROR_INSTALL_UPGRADE_NOT_SUPPORTED ((HRESULT)0x8A150114) +#define APPINSTALLER_CLI_ERROR_INSTALL_CUSTOM_ERROR ((HRESULT)0x8A150115) // Status values for check package installed status results. // Partial success has the success bit(first bit) set to 0. diff --git a/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs b/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs @@ -384,6 +384,7 @@ namespace WinGetUtilInterop.UnitTests.ManifestUnitTest if (manifestVersion >= TestManifestVersion.V190) { Assert.False(installer1.ArchiveBinariesDependOnPath); + Assert.Equal("fakeIdentifier", installer2.ProductId); } // Additional Localizations diff --git a/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_9ManifestMerged.yaml b/src/WinGetUtilInterop.UnitTests/TestCollateral/V1_9ManifestMerged.yaml @@ -246,6 +246,7 @@ Installers: InstallerSha256: 69D84CA8899800A5575CE31798293CD4FEBAB1D734A07C2E51E56A28E0DF8C82 InstallerUrl: https://www.microsoft.com/msixsdk/msixsdkx64.exe InstallerType: exe - ProductCode: '{Bar}' + ProductCode: '{Bar}' + MSStoreProductIdentifier: fakeIdentifier ManifestType: merged -ManifestVersion: 1.7.0- \ No newline at end of file +ManifestVersion: 1.7.0 diff --git a/src/WinGetUtilInterop/Manifest/V1/Manifest.cs b/src/WinGetUtilInterop/Manifest/V1/Manifest.cs @@ -278,17 +278,17 @@ namespace Microsoft.WinGetUtil.Models.V1 /// <summary> /// Gets or sets a value indicating whether the default installer behavior aborts terminal. /// </summary> - public bool InstallerAbortsTerminal { get; set; } + public bool? InstallerAbortsTerminal { get; set; } /// <summary> /// Gets or sets a value indicating whether the default installer behavior requires explicit install location. /// </summary> - public bool InstallLocationRequired { get; set; } + public bool? InstallLocationRequired { get; set; } /// <summary> /// Gets or sets a value indicating whether the default installer behavior requires explicit upgrade. /// </summary> - public bool RequireExplicitUpgrade { get; set; } + public bool? RequireExplicitUpgrade { get; set; } /// <summary> /// Gets or sets the default installer release date. @@ -303,7 +303,7 @@ namespace Microsoft.WinGetUtil.Models.V1 /// <summary> /// Gets or sets a value indicating whether to display install warnings. /// </summary> - public bool DisplayInstallWarnings { get; set; } + public bool? DisplayInstallWarnings { get; set; } /// <summary> /// Gets or sets the default list of apps and features entries. @@ -318,27 +318,17 @@ namespace Microsoft.WinGetUtil.Models.V1 /// <summary> /// Gets or sets the default list of installer expected return codes. /// </summary> - public List<InstallerExpectedReturnCode> ExpectedReturnCodes { get; set; } - - /// <summary> - /// Gets or sets collection of ManifestInstaller. At least one is required. - /// </summary> - public List<ManifestInstaller> Installers { get; set; } - - /// <summary> - /// Gets or sets collection of additional ManifestLocalization. - /// </summary> - public List<ManifestLocalization> Localization { get; set; } - + public List<InstallerExpectedReturnCode> ExpectedReturnCodes { get; set; } + /// <summary> /// Gets or sets a value indicating whether the installer is prohibited from being downloaded for offline installation. /// </summary> - public bool DownloadCommandProhibited { get; set; } + public bool? DownloadCommandProhibited { get; set; } /// <summary> /// Gets or sets a value indicating whether the install location should be added directly to the PATH environment variable. /// </summary> - public bool ArchiveBinariesDependOnPath { get; set; } + public bool? ArchiveBinariesDependOnPath { get; set; } /// <summary> /// Gets or sets the default repair behavior. @@ -346,6 +336,16 @@ namespace Microsoft.WinGetUtil.Models.V1 public string RepairBehavior { get; set; } /// <summary> + /// Gets or sets collection of ManifestInstaller. At least one is required. + /// </summary> + public List<ManifestInstaller> Installers { get; set; } + + /// <summary> + /// Gets or sets collection of additional ManifestLocalization. + /// </summary> + public List<ManifestLocalization> Localization { get; set; } + + /// <summary> /// Deserialize a stream reader into a Manifest object. /// </summary> /// <param name="filePath">file path.</param> diff --git a/src/WinGetUtilInterop/Manifest/V1/ManifestInstaller.cs b/src/WinGetUtilInterop/Manifest/V1/ManifestInstaller.cs @@ -35,7 +35,15 @@ namespace Microsoft.WinGetUtil.Models.V1 /// <summary> /// Gets or sets the signature SHA256 for an appx/msix. Only used by appx/msix type. /// </summary> - public string SignatureSha256 { get; set; } + public string SignatureSha256 { get; set; } + + /// <summary> + /// Gets or sets the Store ProductId. Only used when InstallerType is MSStore. + /// </summary> + [YamlMember(Alias = "MSStoreProductIdentifier")] + public string ProductId { get; set; } + + // Common installer fields that may have defaults in manifest root level. /// <summary> /// Gets or sets the installer locale. @@ -131,17 +139,17 @@ namespace Microsoft.WinGetUtil.Models.V1 /// <summary> /// Gets or sets a value indicating whether the installer behavior aborts terminal. /// </summary> - public bool InstallerAbortsTerminal { get; set; } + public bool? InstallerAbortsTerminal { get; set; } /// <summary> /// Gets or sets a value indicating whether the installer behavior requires explicit install location. /// </summary> - public bool InstallLocationRequired { get; set; } + public bool? InstallLocationRequired { get; set; } /// <summary> /// Gets or sets a value indicating whether the installer behavior requires explicit upgrade. /// </summary> - public bool RequireExplicitUpgrade { get; set; } + public bool? RequireExplicitUpgrade { get; set; } /// <summary> /// Gets or sets the installer release date. @@ -191,17 +199,17 @@ namespace Microsoft.WinGetUtil.Models.V1 /// <summary> /// Gets or sets a value indicating whether to display install warnings. /// </summary> - public bool DisplayInstallWarnings { get; set; } + public bool? DisplayInstallWarnings { get; set; } /// <summary> /// Gets or sets a value indicating whether the installer is prohibited from being downloaded for offline installation. /// </summary> - public bool DownloadCommandProhibited { get; set; } + public bool? DownloadCommandProhibited { get; set; } /// <summary> /// Gets or sets a value indicating whether the install location should be added directly to the PATH environment variable. /// </summary> - public bool ArchiveBinariesDependOnPath { get; set; } + public bool? ArchiveBinariesDependOnPath { get; set; } /// <summary> /// Gets or sets the repair behavior.