diff --git a/doc/windows/package-manager/winget/returnCodes.md b/doc/windows/package-manager/winget/returnCodes.md
index b37fbe5c6e..caad7a5ef4 100644
--- 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
index adf8ce8137..b750747056 100644
--- 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
index 23249c22e3..03ad3db98a 100644
--- 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
index a7fe40578f..d9758d46ce 100644
--- 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
index 90e4c4122c..b8cb13de2e 100644
--- 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
index 1c09ee9ae8..1ca938f73b 100644
--- 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
index cf0e9cc9b7..dcb636fd94 100644
--- 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
index d081e9e61a..d73503efc1 100644
--- 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
index 16f2ad9a1d..833577565a 100644
--- 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
index bffd87e40f..4cdfaa86ad 100644
--- 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
index 71afdd2750..0fcf710f03 100644
--- 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
index 483403fcc6..b0a4d49563 100644
--- 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
index 91464f817a..5d268259b9 100644
--- 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
index 2374071390..b281b91e9c 100644
--- 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
index 1567d0e165..83ae462983 100644
--- 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
index 4ce2e8b3fe..424024c2fd 100644
--- 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
index cfbf745ea6..4940acb829 100644
--- 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
index 8f0de08745..2c5c6903ce 100644
--- 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
index 7e1678e1b0..15781b3950 100644
--- 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
index 2aa7a504ab..5b71ed19e6 100644
--- 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
index a5b00edc5e..89aaca4281 100644
--- 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
index 7cf6502d51..96600dd5a2 100644
--- 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
index 223ac8343d..36b33528b4 100644
--- 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
index 5aa7616509..87abb44340 100644
--- 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
index 8f7081fa13..e85540c379 100644
--- 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
index 46d093b80c..e2c98bbf6d 100644
--- 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?
The current system configuration does not support the installation of this package.
+
+ Installation failed with a custom installer error. Contact package support.
+
Installation abandoned
@@ -2521,6 +2524,9 @@ Please specify one of them using the --source option to proceed.
The installer does not support upgrading an existing package.
+
+ Installation failed with a custom installer error.
+
The Apps and Features Entry for the package could not be found.
@@ -3174,4 +3180,4 @@ Please specify one of them using the --source option to proceed.
Version
-
\ No newline at end of file
+
diff --git a/src/AppInstallerCLITests/YamlManifest.cpp b/src/AppInstallerCLITests/YamlManifest.cpp
index deaa572c64..33b448c79c 100644
--- 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
index 51379004da..ce448c09f9 100644
--- 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(v)->Url = value.as(); return {}; } },
{ "InstallerSha256", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr(v)->Sha256 = Utility::SHA256::ConvertToBytes(value.as()); return {}; } },
{ "SignatureSha256", [](const YAML::Node& value, const VariantManifestPtr& v)->ValidationErrors { variant_ptr(v)->SignatureSha256 = Utility::SHA256::ConvertToBytes(value.as()); 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(v)->ProductId = value.as(); 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
index 92f23dcbc1..62bd3f8d2a 100644
--- 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& 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 items)
+ void ProcessStringSequence(YAML::Emitter& out, std::string_view name, std::vector 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());
ProcessDocumentations(out, manifest.Get());
ProcessIcons(out, manifest.Get());
- ProcessSequence(out, Tags, manifest.Get());
+ ProcessStringSequence(out, Tags, manifest.Get());
WRITE_PROPERTY(out, PackageLocale, manifest.Locale);
WRITE_PROPERTY_IF_EXISTS(out, Author, manifest.Get());
@@ -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
index 87f63ab9ac..73e81ef12e 100644
--- 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
index d00bc8a18a..3524d812bf 100644
--- 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
index 607a427082..ecff759994 100644
--- a/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
+++ b/src/WinGetUtilInterop.UnitTests/ManifestUnitTest/V1ManifestReadTest.cs
@@ -384,6 +384,7 @@ private void ValidateManifestFields(Manifest manifest, TestManifestVersion manif
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
index 28e92896a4..3bf371df37 100644
--- 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
index 534d29af4a..811081064c 100644
--- a/src/WinGetUtilInterop/Manifest/V1/Manifest.cs
+++ b/src/WinGetUtilInterop/Manifest/V1/Manifest.cs
@@ -278,17 +278,17 @@ public class Manifest
///
/// Gets or sets a value indicating whether the default installer behavior aborts terminal.
///
- public bool InstallerAbortsTerminal { get; set; }
+ public bool? InstallerAbortsTerminal { get; set; }
///
/// Gets or sets a value indicating whether the default installer behavior requires explicit install location.
///
- public bool InstallLocationRequired { get; set; }
+ public bool? InstallLocationRequired { get; set; }
///
/// Gets or sets a value indicating whether the default installer behavior requires explicit upgrade.
///
- public bool RequireExplicitUpgrade { get; set; }
+ public bool? RequireExplicitUpgrade { get; set; }
///
/// Gets or sets the default installer release date.
@@ -303,7 +303,7 @@ public class Manifest
///
/// Gets or sets a value indicating whether to display install warnings.
///
- public bool DisplayInstallWarnings { get; set; }
+ public bool? DisplayInstallWarnings { get; set; }
///
/// Gets or sets the default list of apps and features entries.
@@ -318,33 +318,33 @@ public class Manifest
///
/// Gets or sets the default list of installer expected return codes.
///
- public List ExpectedReturnCodes { get; set; }
-
- ///
- /// Gets or sets collection of ManifestInstaller. At least one is required.
- ///
- public List Installers { get; set; }
-
- ///
- /// Gets or sets collection of additional ManifestLocalization.
- ///
- public List Localization { get; set; }
-
+ public List ExpectedReturnCodes { get; set; }
+
///
/// Gets or sets a value indicating whether the installer is prohibited from being downloaded for offline installation.
///
- public bool DownloadCommandProhibited { get; set; }
+ public bool? DownloadCommandProhibited { get; set; }
///
/// Gets or sets a value indicating whether the install location should be added directly to the PATH environment variable.
///
- public bool ArchiveBinariesDependOnPath { get; set; }
+ public bool? ArchiveBinariesDependOnPath { get; set; }
///
/// Gets or sets the default repair behavior.
///
public string RepairBehavior { get; set; }
+ ///
+ /// Gets or sets collection of ManifestInstaller. At least one is required.
+ ///
+ public List Installers { get; set; }
+
+ ///
+ /// Gets or sets collection of additional ManifestLocalization.
+ ///
+ public List Localization { get; set; }
+
///
/// Deserialize a stream reader into a Manifest object.
///
diff --git a/src/WinGetUtilInterop/Manifest/V1/ManifestInstaller.cs b/src/WinGetUtilInterop/Manifest/V1/ManifestInstaller.cs
index 1f84a1da04..c6e326e3e3 100644
--- a/src/WinGetUtilInterop/Manifest/V1/ManifestInstaller.cs
+++ b/src/WinGetUtilInterop/Manifest/V1/ManifestInstaller.cs
@@ -35,7 +35,15 @@ public class ManifestInstaller
///
/// Gets or sets the signature SHA256 for an appx/msix. Only used by appx/msix type.
///
- public string SignatureSha256 { get; set; }
+ public string SignatureSha256 { get; set; }
+
+ ///
+ /// Gets or sets the Store ProductId. Only used when InstallerType is MSStore.
+ ///
+ [YamlMember(Alias = "MSStoreProductIdentifier")]
+ public string ProductId { get; set; }
+
+ // Common installer fields that may have defaults in manifest root level.
///
/// Gets or sets the installer locale.
@@ -131,17 +139,17 @@ public class ManifestInstaller
///
/// Gets or sets a value indicating whether the installer behavior aborts terminal.
///
- public bool InstallerAbortsTerminal { get; set; }
+ public bool? InstallerAbortsTerminal { get; set; }
///
/// Gets or sets a value indicating whether the installer behavior requires explicit install location.
///
- public bool InstallLocationRequired { get; set; }
+ public bool? InstallLocationRequired { get; set; }
///
/// Gets or sets a value indicating whether the installer behavior requires explicit upgrade.
///
- public bool RequireExplicitUpgrade { get; set; }
+ public bool? RequireExplicitUpgrade { get; set; }
///
/// Gets or sets the installer release date.
@@ -191,17 +199,17 @@ public class ManifestInstaller
///
/// Gets or sets a value indicating whether to display install warnings.
///
- public bool DisplayInstallWarnings { get; set; }
+ public bool? DisplayInstallWarnings { get; set; }
///
/// Gets or sets a value indicating whether the installer is prohibited from being downloaded for offline installation.
///
- public bool DownloadCommandProhibited { get; set; }
+ public bool? DownloadCommandProhibited { get; set; }
///
/// Gets or sets a value indicating whether the install location should be added directly to the PATH environment variable.
///
- public bool ArchiveBinariesDependOnPath { get; set; }
+ public bool? ArchiveBinariesDependOnPath { get; set; }
///
/// Gets or sets the repair behavior.