Skip to content

Commit 86d91e3

Browse files
committed
Add COM+PS values for Store options (skip license, platform, target os version) and test update
1 parent fd0aa12 commit 86d91e3

File tree

12 files changed

+277
-5
lines changed

12 files changed

+277
-5
lines changed

src/AppInstallerCLI.sln

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ VisualStudioVersion = 17.2.32630.192
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "AppInstallerCLIPackage", "AppInstallerCLIPackage\AppInstallerCLIPackage.wapproj", "{6AA3791A-0713-4548-A357-87A323E7AC3A}"
77
ProjectSection(ProjectDependencies) = postProject
8+
{0BA531C8-CF0C-405B-8221-0FE51BA529D1} = {0BA531C8-CF0C-405B-8221-0FE51BA529D1}
89
{1CC41A9A-AE66-459D-9210-1E572DD7BE69} = {1CC41A9A-AE66-459D-9210-1E572DD7BE69}
910
{2B00D362-AC92-41F3-A8D2-5B1599BDCA01} = {2B00D362-AC92-41F3-A8D2-5B1599BDCA01}
11+
{33745E4A-39E2-676F-7E23-50FB43848D25} = {33745E4A-39E2-676F-7E23-50FB43848D25}
1012
{5B6F90DF-FD19-4BAE-83D9-24DAD128E777} = {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}
1113
{6597EB04-D105-49A7-A5A3-D27FE1DF895E} = {6597EB04-D105-49A7-A5A3-D27FE1DF895E}
1214
{CA460806-5E41-4E97-9A3D-1D74B433B663} = {CA460806-5E41-4E97-9A3D-1D74B433B663}

src/AppInstallerCLITests/MSStoreDownloadFlow.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,19 @@ std::vector<SFS::AppContent> GetSfsAppContentsOverrideFunction(std::string_view
133133
dependencyX64);
134134
dependencyPackages.emplace_back(std::move(*dependencyX64));
135135

136+
// Lower target OS dependency
137+
std::unique_ptr<SFS::AppFile> dependencyX64_lower;
138+
std::ignore = SFS::AppFile::Make(
139+
wuCategoryIdStr + ".appx",
140+
"https://NotUsed/" + wuCategoryIdStr + "/dependency/x64",
141+
100,
142+
{ { SFS::HashType::Sha256, base64EncodedSha256 } },
143+
{ SFS::Architecture::Amd64 },
144+
{ "Universal=9.0.0.0" },
145+
wuCategoryIdStr + ".Dependency_0.9.3.4_x64__8wekyb3d8bbwe",
146+
dependencyX64_lower);
147+
dependencyPackages.emplace_back(std::move(*dependencyX64_lower));
148+
136149
std::unique_ptr<SFS::AppFile> dependencyArm;
137150
std::ignore = SFS::AppFile::Make(
138151
wuCategoryIdStr + ".appx",
@@ -166,6 +179,19 @@ std::vector<SFS::AppContent> GetSfsAppContentsOverrideFunction(std::string_view
166179
packageX64);
167180
packages.emplace_back(std::move(*packageX64));
168181

182+
// Good candidate x64, lower minimum OS version, lower package version
183+
std::unique_ptr<SFS::AppFile> packageX64_lower;
184+
std::ignore = SFS::AppFile::Make(
185+
wuCategoryIdStr + ".appx",
186+
"https://NotUsed/" + wuCategoryIdStr + "/x64",
187+
100,
188+
{ { SFS::HashType::Sha256, base64EncodedSha256 } },
189+
{ SFS::Architecture::Amd64 },
190+
{ "Desktop=9.0.0.0" },
191+
wuCategoryIdStr + "_0.9.0.0_x64__8wekyb3d8bbwe",
192+
packageX64_lower);
193+
packages.emplace_back(std::move(*packageX64_lower));
194+
169195
// Good candidate arm
170196
std::unique_ptr<SFS::AppFile> packageArm;
171197
std::ignore = SFS::AppFile::Make(
@@ -595,3 +621,43 @@ TEST_CASE("MSStoreDownloadFlow_Fail_Licensing_Forbidden", "[MSStoreDownloadFlow]
595621
REQUIRE_TERMINATED_WITH(context, APPINSTALLER_CLI_ERROR_LICENSING_API_FAILED_FORBIDDEN);
596622
INFO(downloadOutput.str());
597623
}
624+
625+
TEST_CASE("MSStoreDownloadFlow_Success_TargetOSVersion", "[MSStoreDownloadFlow][workflow]")
626+
{
627+
TestCommon::TempDirectory tempDirectory("TestDownloadDirectory", false);
628+
629+
std::ostringstream downloadOutput;
630+
TestContext context{ downloadOutput, std::cin };
631+
auto previousThreadGlobals = context.SetForCurrentThread();
632+
OverrideDownloadInstallerFileForMSStoreDownload(context);
633+
TestHook::SetDisplayCatalogHttpPipelineStage_Override displayCatalogOverride(GetTestRestRequestHandler(web::http::status_codes::OK, TestDisplayCatalogResponse));
634+
TestHook::SetSfsClientAppContents_Override sfsClientOverride({ &GetSfsAppContentsOverrideFunction });
635+
TestHook::SetLicensingHttpPipelineStage_Override licensingOverride(GetTestRestRequestHandler(web::http::status_codes::OK, TestLicensingResponse));
636+
context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("DownloadFlowTest_MSStore.yaml").GetPath().u8string());
637+
context.Args.AddArg(Execution::Args::Type::DownloadDirectory, tempDirectory);
638+
context.Args.AddArg(Execution::Args::Type::Locale, "en-US"sv);
639+
context.Args.AddArg(Execution::Args::Type::Platform, "Windows.Desktop"sv);
640+
context.Args.AddArg(Execution::Args::Type::OSVersion, "9.0.0.0"sv);
641+
642+
DownloadCommand download({});
643+
download.Execute(context);
644+
REQUIRE(context.GetTerminationHR() == S_OK);
645+
INFO(downloadOutput.str());
646+
647+
// Verify downloaded files
648+
REQUIRE(std::filesystem::exists(tempDirectory.GetPath()));
649+
REQUIRE(std::filesystem::exists(tempDirectory.GetPath() / L"Dependencies"));
650+
REQUIRE(std::filesystem::exists(tempDirectory.GetPath() / L"Dependencies" / L"TestCategoryIdEnglish.Dependency_0.9.3.4_Universal_X64.appx"));
651+
REQUIRE_FALSE(std::filesystem::exists(tempDirectory.GetPath() / L"Dependencies" / L"TestCategoryIdEnglish.Dependency_1.2.3.4_Universal_Arm.appx"));
652+
REQUIRE(std::filesystem::exists(tempDirectory.GetPath() / L"TestCategoryIdEnglish_0.9.0.0_Desktop_X64.appx"));
653+
REQUIRE_FALSE(std::filesystem::exists(tempDirectory.GetPath() / L"TestCategoryIdEnglish_1.0.0.0_Desktop_Arm.appx"));
654+
REQUIRE_FALSE(std::filesystem::exists(tempDirectory.GetPath() / L"TestCategoryIdEnglish.IoT_2.0.0.0_IoT_Arm.appx"));
655+
656+
// Verify license
657+
REQUIRE(std::filesystem::exists(tempDirectory.GetPath() / L"9WZDNCRFJ364_License.xml"));
658+
std::ifstream licenseFile(tempDirectory.GetPath() / L"9WZDNCRFJ364_License.xml");
659+
REQUIRE(licenseFile.is_open());
660+
std::string licenseFileStr;
661+
std::getline(licenseFile, licenseFileStr);
662+
REQUIRE(licenseFileStr == LicenseContent);
663+
}

src/Microsoft.Management.Deployment/Converters.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,4 +530,17 @@ namespace winrt::Microsoft::Management::Deployment::implementation
530530
}
531531
}
532532

533+
::AppInstaller::Manifest::PlatformEnum GetPlatformEnum(WindowsPlatform value)
534+
{
535+
switch (value)
536+
{
537+
case WindowsPlatform::Unknown: return AppInstaller::Manifest::PlatformEnum::Unknown;
538+
case WindowsPlatform::Universal: return AppInstaller::Manifest::PlatformEnum::Universal;
539+
case WindowsPlatform::Desktop: return AppInstaller::Manifest::PlatformEnum::Desktop;
540+
case WindowsPlatform::IoT: return AppInstaller::Manifest::PlatformEnum::IoT;
541+
case WindowsPlatform::Team: return AppInstaller::Manifest::PlatformEnum::Team;
542+
case WindowsPlatform::Holographic: return AppInstaller::Manifest::PlatformEnum::Holographic;
543+
default: return AppInstaller::Manifest::PlatformEnum::Unknown;
544+
}
545+
}
533546
}

src/Microsoft.Management.Deployment/Converters.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace winrt::Microsoft::Management::Deployment::implementation
3333
::AppInstaller::Manifest::ScopeEnum GetManifestRepairScope(winrt::Microsoft::Management::Deployment::PackageRepairScope scope);
3434
winrt::Microsoft::Management::Deployment::AddPackageCatalogStatus GetAddPackageCatalogOperationStatus(winrt::hresult hresult);
3535
winrt::Microsoft::Management::Deployment::RemovePackageCatalogStatus GetRemovePackageCatalogOperationStatus(winrt::hresult hresult);
36+
::AppInstaller::Manifest::PlatformEnum GetPlatformEnum(winrt::Microsoft::Management::Deployment::WindowsPlatform value);
3637

3738
#define WINGET_GET_OPERATION_RESULT_STATUS(_installResultStatus_, _uninstallResultStatus_, _downloadResultStatus_, _repairResultStatus_) \
3839
if constexpr (std::is_same_v<TStatus, winrt::Microsoft::Management::Deployment::InstallResultStatus>) \

src/Microsoft.Management.Deployment/DownloadOptions.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,37 @@ namespace winrt::Microsoft::Management::Deployment::implementation
105105
void DownloadOptions::AuthenticationArguments(winrt::Microsoft::Management::Deployment::AuthenticationArguments const& value)
106106
{
107107
m_authenticationArguments = value;
108-
}
108+
}
109+
110+
bool DownloadOptions::SkipMicrosoftStoreLicense()
111+
{
112+
return m_skipMicrosoftStoreLicense;
113+
}
114+
115+
void DownloadOptions::SkipMicrosoftStoreLicense(bool value)
116+
{
117+
m_skipMicrosoftStoreLicense = value;
118+
}
119+
120+
winrt::Microsoft::Management::Deployment::WindowsPlatform DownloadOptions::Platform()
121+
{
122+
return m_platform;
123+
}
124+
125+
void DownloadOptions::Platform(winrt::Microsoft::Management::Deployment::WindowsPlatform value)
126+
{
127+
m_platform = value;
128+
}
129+
130+
hstring DownloadOptions::TargetOSVersion()
131+
{
132+
return hstring(m_targetOSVersion);
133+
}
134+
135+
void DownloadOptions::TargetOSVersion(hstring const& value)
136+
{
137+
m_targetOSVersion = value;
138+
}
139+
109140
CoCreatableMicrosoftManagementDeploymentClass(DownloadOptions);
110141
}

src/Microsoft.Management.Deployment/DownloadOptions.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ namespace winrt::Microsoft::Management::Deployment::implementation
3333
void CorrelationData(hstring const& value);
3434
winrt::Microsoft::Management::Deployment::AuthenticationArguments AuthenticationArguments();
3535
void AuthenticationArguments(winrt::Microsoft::Management::Deployment::AuthenticationArguments const& value);
36+
bool SkipMicrosoftStoreLicense();
37+
void SkipMicrosoftStoreLicense(bool value);
38+
winrt::Microsoft::Management::Deployment::WindowsPlatform Platform();
39+
void Platform(winrt::Microsoft::Management::Deployment::WindowsPlatform value);
40+
hstring TargetOSVersion();
41+
void TargetOSVersion(hstring const& value);
3642

3743
#if !defined(INCLUDE_ONLY_INTERFACE_METHODS)
3844
private:
@@ -47,6 +53,9 @@ namespace winrt::Microsoft::Management::Deployment::implementation
4753
bool m_acceptPackageAgreements = true;
4854
std::wstring m_correlationData = L"";
4955
winrt::Microsoft::Management::Deployment::AuthenticationArguments m_authenticationArguments{ nullptr };
56+
bool m_skipMicrosoftStoreLicense = false;
57+
winrt::Microsoft::Management::Deployment::WindowsPlatform m_platform = winrt::Microsoft::Management::Deployment::WindowsPlatform::Unknown;
58+
std::wstring m_targetOSVersion;
5059
#endif
5160
};
5261
}

src/Microsoft.Management.Deployment/PackageManager.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,23 @@ namespace winrt::Microsoft::Management::Deployment::implementation
690690
context->Args.AddArg(Execution::Args::Type::AuthenticationMode, ::AppInstaller::Authentication::AuthenticationModeToString(GetAuthenticationMode(options.AuthenticationArguments().AuthenticationMode())));
691691
context->Args.AddArg(Execution::Args::Type::AuthenticationAccount, ::AppInstaller::Utility::ConvertToUTF8(options.AuthenticationArguments().AuthenticationAccount()));
692692
}
693+
694+
if (options.SkipMicrosoftStoreLicense())
695+
{
696+
context->Args.AddArg(Execution::Args::Type::SkipMicrosoftStorePackageLicense);
697+
}
698+
699+
WindowsPlatform platform = options.Platform();
700+
if (platform != WindowsPlatform::Unknown)
701+
{
702+
context->Args.AddArg(Execution::Args::Type::Platform, AppInstaller::Manifest::PlatformToString(GetPlatformEnum(platform)));
703+
}
704+
705+
hstring targetOSVersion = options.TargetOSVersion();
706+
if (!targetOSVersion.empty())
707+
{
708+
context->Args.AddArg(Execution::Args::Type::OSVersion, ::AppInstaller::Utility::ConvertToUTF8(targetOSVersion));
709+
}
693710
}
694711
}
695712

src/Microsoft.Management.Deployment/PackageManager.idl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,24 @@ namespace Microsoft.Management.Deployment
11591159
}
11601160
}
11611161

1162+
/// The Windows platform type.
1163+
[contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 13)]
1164+
enum WindowsPlatform
1165+
{
1166+
/// An unknown platform
1167+
Unknown,
1168+
/// Windows.Universal
1169+
Universal,
1170+
/// Windows.Desktop
1171+
Desktop,
1172+
/// Windows.IoT
1173+
IoT,
1174+
/// Windows.Team
1175+
Team,
1176+
/// Windows.Holographic
1177+
Holographic,
1178+
};
1179+
11621180
/// Options when downloading a package.
11631181
/// Intended to allow full compatibility with the "winget download" command line interface.
11641182
[contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 7)]
@@ -1203,6 +1221,18 @@ namespace Microsoft.Management.Deployment
12031221
/// Authentication arguments used when downloading the package installer if authentication is required.
12041222
AuthenticationArguments AuthenticationArguments;
12051223
}
1224+
1225+
[contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 13)]
1226+
{
1227+
/// If the package is licensed from the Microsoft Store, setting this value to true will not attempt to download the license file.
1228+
Boolean SkipMicrosoftStoreLicense;
1229+
1230+
/// The platform to download the package for.
1231+
WindowsPlatform Platform;
1232+
1233+
/// When applicable, uses the provided value as the target OS version for the download.
1234+
String TargetOSVersion;
1235+
}
12061236
}
12071237

12081238
[contract(Microsoft.Management.Deployment.WindowsPackageManagerContract, 11)]

src/PowerShell/Microsoft.WinGet.Client.Cmdlets/Cmdlets/ExportPackageCmdlet.cs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// -----------------------------------------------------------------------------
1+
// -----------------------------------------------------------------------------
22
// <copyright file="ExportPackageCmdlet.cs" company="Microsoft Corporation">
33
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
44
// </copyright>
@@ -31,6 +31,24 @@ public sealed class ExportPackageCmdlet : InstallerSelectionCmdlet
3131
[Parameter(ValueFromPipelineByPropertyName = true)]
3232
public string DownloadDirectory { get; set; }
3333

34+
/// <summary>
35+
/// Gets or sets a value indicating whether to skip acquiring the license from a Store package.
36+
/// </summary>
37+
[Parameter(ValueFromPipelineByPropertyName = true)]
38+
public SwitchParameter SkipMicrosoftStoreLicense { get; set; }
39+
40+
/// <summary>
41+
/// Gets or sets the platform to download the package for.
42+
/// </summary>
43+
[Parameter(ValueFromPipelineByPropertyName = true)]
44+
public PSObjects.PSWindowsPlatform Platform { get; set; }
45+
46+
/// <summary>
47+
/// Gets or sets the target OS version to download for.
48+
/// </summary>
49+
[Parameter(ValueFromPipelineByPropertyName = true)]
50+
public string TargetOSVersion { get; set; }
51+
3452
/// <summary>
3553
/// Installs a package from the pipeline or from a configured source.
3654
/// </summary>
@@ -48,7 +66,15 @@ protected override void ProcessRecord()
4866
this.AllowHashMismatch.ToBool(),
4967
this.SkipDependencies.ToBool(),
5068
this.Locale);
51-
this.command.Download(this.DownloadDirectory, this.MatchOption.ToString(), this.Scope.ToString(), this.Architecture.ToString(), this.InstallerType.ToString());
69+
this.command.Download(
70+
this.DownloadDirectory,
71+
this.MatchOption.ToString(),
72+
this.Scope.ToString(),
73+
this.Architecture.ToString(),
74+
this.InstallerType.ToString(),
75+
this.SkipMicrosoftStoreLicense.ToBool(),
76+
this.Platform.ToString(),
77+
this.TargetOSVersion);
5278
}
5379

5480
/// <summary>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// -----------------------------------------------------------------------------
2+
// <copyright file="PSWindowsPlatform.cs" company="Microsoft Corporation">
3+
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
4+
// </copyright>
5+
// -----------------------------------------------------------------------------
6+
7+
namespace Microsoft.WinGet.Client.PSObjects
8+
{
9+
/// <summary>
10+
/// The Windows platform type.
11+
/// </summary>
12+
public enum PSWindowsPlatform
13+
{
14+
/// <summary>
15+
/// Let winget decide.
16+
/// </summary>
17+
Default,
18+
19+
/// <summary>
20+
/// Windows.Universal
21+
/// </summary>
22+
Universal,
23+
24+
/// <summary>
25+
/// Windows.Desktop
26+
/// </summary>
27+
Desktop,
28+
29+
/// <summary>
30+
/// Windows.IoT
31+
/// </summary>
32+
IoT,
33+
34+
/// <summary>
35+
/// Windows.Team
36+
/// </summary>
37+
Team,
38+
39+
/// <summary>
40+
/// Windows.Holographic
41+
/// </summary>
42+
Holographic,
43+
}
44+
}

0 commit comments

Comments
 (0)