From 2fff3d2f3600f15886b7bb3864c5c8619c012eaa Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Tue, 4 Apr 2023 15:51:33 -0500 Subject: [PATCH 01/15] Show Portable Installation Directories with --info --- src/AppInstallerCLICore/Commands/RootCommand.cpp | 14 +++++++++++++- src/AppInstallerCLICore/Resources.h | 1 + .../Shared/Strings/en-us/winget.resw | 4 ++++ src/AppInstallerCommonCore/Filesystem.cpp | 7 +++++++ .../Public/AppInstallerRuntime.h | 4 ++-- .../Public/winget/Filesystem.h | 4 ++++ src/AppInstallerCommonCore/Runtime.cpp | 16 ++++++++++------ 7 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp index 255f3ae807..9cdbaf4787 100644 --- a/src/AppInstallerCLICore/Commands/RootCommand.cpp +++ b/src/AppInstallerCLICore/Commands/RootCommand.cpp @@ -126,6 +126,18 @@ namespace AppInstaller::CLI } adminSettingsTable.Complete(); } + + void OutputPortableDirectories(Execution::Context& context) + { + Execution::TableOutput<2> portableRoots{ context.Reporter, { Resource::String::PortableDirectoriesHeader, {} } }; + portableRoots.OutputLine({ "Portable Links Directory (User)", Runtime::GetPathTo(Runtime::PathName::PortableLinksUserLocation, true).string() }); + portableRoots.OutputLine({ "Portable Links Directory (Machine)", Runtime::GetPathTo(Runtime::PathName::PortableLinksMachineLocation, true).string() }); + portableRoots.OutputLine({ "Portable Package Root (User)", Runtime::GetPathTo(Runtime::PathName::PortablePackageUserRoot, true).string() }); + portableRoots.OutputLine({ "Portable Package Root (x86)", Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX86, true).string() }); + portableRoots.OutputLine({ "Portable Package Root (x64)", Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX64, true).string() }); + portableRoots.Complete(); + context.Reporter.Info() << std::endl; + } } std::vector> RootCommand::GetCommands() const @@ -213,7 +225,6 @@ namespace AppInstaller::CLI info << std::endl << Resource::String::Logs(Utility::LocIndView{ Runtime::GetPathTo(Runtime::PathName::DefaultLogLocationForDisplay).u8string() }) << std::endl; info << std::endl << Resource::String::UserSettings(Utility::LocIndView{ UserSettings::SettingsFilePath(true).u8string() }) << std::endl; - info << std::endl; Execution::TableOutput<2> links{ context.Reporter, { Resource::String::Links, {} } }; @@ -227,6 +238,7 @@ namespace AppInstaller::CLI links.Complete(); info << std::endl; + OutputPortableDirectories(context); OutputGroupPolicies(context); OutputAdminSettings(context); } diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h index bff7ff6f76..7f5c07f9b9 100644 --- a/src/AppInstallerCLICore/Resources.h +++ b/src/AppInstallerCLICore/Resources.h @@ -311,6 +311,7 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(PortableHashMismatchOverridden); WINGET_DEFINE_RESOURCE_STRINGID(PortableHashMismatchOverrideRequired); WINGET_DEFINE_RESOURCE_STRINGID(PortableAliasAdded); + WINGET_DEFINE_RESOURCE_STRINGID(PortableDirectoriesHeader); WINGET_DEFINE_RESOURCE_STRINGID(PortableInstallFailed); WINGET_DEFINE_RESOURCE_STRINGID(PortablePackageAlreadyExists); WINGET_DEFINE_RESOURCE_STRINGID(PortableRegistryCollisionOverridden); diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index 24775cb6b1..b13d4259e6 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -1402,6 +1402,10 @@ Please specify one of them using the --source option to proceed. Command line alias added: + + Portable Installation Directories + Header for a table detailing the user's configured directories for portable installs + Portable install failed; Cleaning up... diff --git a/src/AppInstallerCommonCore/Filesystem.cpp b/src/AppInstallerCommonCore/Filesystem.cpp index e194710832..46b75b7762 100644 --- a/src/AppInstallerCommonCore/Filesystem.cpp +++ b/src/AppInstallerCommonCore/Filesystem.cpp @@ -236,6 +236,13 @@ namespace AppInstaller::Filesystem return false; } + bool AnonymizeFilePath(std::filesystem::path& source) + { + bool replaced = ReplaceCommonPathPrefix(source, GetKnownFolderPath(FOLDERID_LocalAppData), "%LOCALAPPDATA%"); + replaced = ReplaceCommonPathPrefix(source, GetKnownFolderPath(FOLDERID_RoamingAppData), "%APPDATA%") && replaced; + return replaced; + } + std::filesystem::path GetKnownFolderPath(const KNOWNFOLDERID& id) { wil::unique_cotaskmem_string knownFolder = nullptr; diff --git a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h index 8683b567ad..2820cd057b 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h @@ -112,10 +112,10 @@ namespace AppInstaller::Runtime // Gets the PathDetails used for the given path. // This is exposed primarily to allow for testing, GetPathTo should be preferred. - PathDetails GetPathDetailsFor(PathName path); + PathDetails GetPathDetailsFor(PathName path, bool anonymize = false); // Gets the path to the requested location. - std::filesystem::path GetPathTo(PathName path); + std::filesystem::path GetPathTo(PathName path, bool anonymize = false); // Gets a new temp file path. std::filesystem::path GetNewTempFilePath(); diff --git a/src/AppInstallerCommonCore/Public/winget/Filesystem.h b/src/AppInstallerCommonCore/Public/winget/Filesystem.h index 0e202ace16..3071e1eee2 100644 --- a/src/AppInstallerCommonCore/Public/winget/Filesystem.h +++ b/src/AppInstallerCommonCore/Public/winget/Filesystem.h @@ -41,6 +41,10 @@ namespace AppInstaller::Filesystem // Returns true if replacement happened, false otherwise. bool ReplaceCommonPathPrefix(std::filesystem::path& source, const std::filesystem::path& prefix, std::string_view replacement); + // If the path begins with a common prefix for APPDATA or LOCALAPPDATA, replace it with the anonymized version + // Returns true if replacement happened, false otherwise. + bool AnonymizeFilePath(std::filesystem::path& source); + // Gets the path of a known folder. std::filesystem::path GetKnownFolderPath(const KNOWNFOLDERID& id); diff --git a/src/AppInstallerCommonCore/Runtime.cpp b/src/AppInstallerCommonCore/Runtime.cpp index 2347c719c6..ce70da8409 100644 --- a/src/AppInstallerCommonCore/Runtime.cpp +++ b/src/AppInstallerCommonCore/Runtime.cpp @@ -485,7 +485,7 @@ namespace AppInstaller::Runtime } #ifndef WINGET_DISABLE_FOR_FUZZING - PathDetails GetPathDetailsForPackagedContext(PathName path) + PathDetails GetPathDetailsForPackagedContext(PathName path, bool anonymize) { PathDetails result; @@ -511,7 +511,7 @@ namespace AppInstaller::Runtime if (path == PathName::DefaultLogLocationForDisplay) { - ReplaceCommonPathPrefix(result.Path, GetKnownFolderPath(FOLDERID_LocalAppData), "%LOCALAPPDATA%"); + AnonymizeFilePath(result.Path); } break; case PathName::StandardSettings: @@ -542,6 +542,10 @@ namespace AppInstaller::Runtime case PathName::PortableLinksUserLocation: case PathName::PortableLinksMachineLocation: result = GetPathDetailsCommon(path); + if (anonymize) + { + AnonymizeFilePath(result.Path); + } break; case PathName::SelfPackageRoot: result.Path = GetPackagePath(); @@ -629,14 +633,14 @@ namespace AppInstaller::Runtime return result; } - PathDetails GetPathDetailsFor(PathName path) + PathDetails GetPathDetailsFor(PathName path, bool anonymize) { PathDetails result; #ifndef WINGET_DISABLE_FOR_FUZZING if (IsRunningInPackagedContext()) { - result = GetPathDetailsForPackagedContext(path); + result = GetPathDetailsForPackagedContext(path, anonymize); } else #endif @@ -656,9 +660,9 @@ namespace AppInstaller::Runtime return result; } - std::filesystem::path GetPathTo(PathName path) + std::filesystem::path GetPathTo(PathName path, bool anonymize) { - PathDetails details = GetPathDetailsFor(path); + PathDetails details = GetPathDetailsFor(path, anonymize); if (details.Create) { From f124a0502c0d04b80b59e4a39b9e6da591c2536e Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Wed, 5 Apr 2023 14:36:35 -0500 Subject: [PATCH 02/15] Localize directory names --- src/AppInstallerCLICore/Commands/RootCommand.cpp | 10 +++++----- src/AppInstallerCLICore/Resources.h | 5 +++++ .../Shared/Strings/en-us/winget.resw | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp index 9cdbaf4787..7c43657909 100644 --- a/src/AppInstallerCLICore/Commands/RootCommand.cpp +++ b/src/AppInstallerCLICore/Commands/RootCommand.cpp @@ -130,11 +130,11 @@ namespace AppInstaller::CLI void OutputPortableDirectories(Execution::Context& context) { Execution::TableOutput<2> portableRoots{ context.Reporter, { Resource::String::PortableDirectoriesHeader, {} } }; - portableRoots.OutputLine({ "Portable Links Directory (User)", Runtime::GetPathTo(Runtime::PathName::PortableLinksUserLocation, true).string() }); - portableRoots.OutputLine({ "Portable Links Directory (Machine)", Runtime::GetPathTo(Runtime::PathName::PortableLinksMachineLocation, true).string() }); - portableRoots.OutputLine({ "Portable Package Root (User)", Runtime::GetPathTo(Runtime::PathName::PortablePackageUserRoot, true).string() }); - portableRoots.OutputLine({ "Portable Package Root (x86)", Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX86, true).string() }); - portableRoots.OutputLine({ "Portable Package Root (x64)", Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX64, true).string() }); + portableRoots.OutputLine({ Resource::LocString{ Resource::String::PortableLinksUser }, Runtime::GetPathTo(Runtime::PathName::PortableLinksUserLocation, true).string() }); + portableRoots.OutputLine({ Resource::LocString{ Resource::String::PortableLinksMachine }, Runtime::GetPathTo(Runtime::PathName::PortableLinksMachineLocation, true).string() }); + portableRoots.OutputLine({ Resource::LocString{ Resource::String::PortableRootUser }, Runtime::GetPathTo(Runtime::PathName::PortablePackageUserRoot, true).string() }); + portableRoots.OutputLine({ Resource::LocString{ Resource::String::PortableRoot64 }, Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX86, true).string() }); + portableRoots.OutputLine({ Resource::LocString{ Resource::String::PortableRoot86 }, Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX64, true).string() }); portableRoots.Complete(); context.Reporter.Info() << std::endl; } diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h index 7f5c07f9b9..a3481c26be 100644 --- a/src/AppInstallerCLICore/Resources.h +++ b/src/AppInstallerCLICore/Resources.h @@ -312,6 +312,11 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(PortableHashMismatchOverrideRequired); WINGET_DEFINE_RESOURCE_STRINGID(PortableAliasAdded); WINGET_DEFINE_RESOURCE_STRINGID(PortableDirectoriesHeader); + WINGET_DEFINE_RESOURCE_STRINGID(PortableLinksMachine); + WINGET_DEFINE_RESOURCE_STRINGID(PortableLinksUser); + WINGET_DEFINE_RESOURCE_STRINGID(PortableRootUser); + WINGET_DEFINE_RESOURCE_STRINGID(PortableRoot64); + WINGET_DEFINE_RESOURCE_STRINGID(PortableRoot86); WINGET_DEFINE_RESOURCE_STRINGID(PortableInstallFailed); WINGET_DEFINE_RESOURCE_STRINGID(PortablePackageAlreadyExists); WINGET_DEFINE_RESOURCE_STRINGID(PortableRegistryCollisionOverridden); diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index b13d4259e6..8c19f09641 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -1406,6 +1406,21 @@ Please specify one of them using the --source option to proceed. Portable Installation Directories Header for a table detailing the user's configured directories for portable installs + + Portable Links Directory (Machine) + + + Portable Links Directory (User) + + + Portable Package Root (User) + + + Portable Package Root (x86) + + + Portable Package Root (x64) + Portable install failed; Cleaning up... From 1c4debf2474e9b1752297327f1435b296eb4fc57 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Wed, 5 Apr 2023 14:42:55 -0500 Subject: [PATCH 03/15] Revert Util function --- .../Public/AppInstallerRuntime.h | 4 ++-- src/AppInstallerCommonCore/Runtime.cpp | 17 +++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h index 2820cd057b..28c8edfc97 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h @@ -112,10 +112,10 @@ namespace AppInstaller::Runtime // Gets the PathDetails used for the given path. // This is exposed primarily to allow for testing, GetPathTo should be preferred. - PathDetails GetPathDetailsFor(PathName path, bool anonymize = false); + PathDetails GetPathDetailsFor(PathName path, bool forDisplay = false); // Gets the path to the requested location. - std::filesystem::path GetPathTo(PathName path, bool anonymize = false); + std::filesystem::path GetPathTo(PathName path, bool forDisplay = false); // Gets a new temp file path. std::filesystem::path GetNewTempFilePath(); diff --git a/src/AppInstallerCommonCore/Runtime.cpp b/src/AppInstallerCommonCore/Runtime.cpp index ce70da8409..3ab4f0c262 100644 --- a/src/AppInstallerCommonCore/Runtime.cpp +++ b/src/AppInstallerCommonCore/Runtime.cpp @@ -485,7 +485,7 @@ namespace AppInstaller::Runtime } #ifndef WINGET_DISABLE_FOR_FUZZING - PathDetails GetPathDetailsForPackagedContext(PathName path, bool anonymize) + PathDetails GetPathDetailsForPackagedContext(PathName path, bool forDisplay) { PathDetails result; @@ -511,7 +511,7 @@ namespace AppInstaller::Runtime if (path == PathName::DefaultLogLocationForDisplay) { - AnonymizeFilePath(result.Path); + ReplaceCommonPathPrefix(result.Path, GetKnownFolderPath(FOLDERID_LocalAppData), "%LOCALAPPDATA%"); } break; case PathName::StandardSettings: @@ -542,9 +542,10 @@ namespace AppInstaller::Runtime case PathName::PortableLinksUserLocation: case PathName::PortableLinksMachineLocation: result = GetPathDetailsCommon(path); - if (anonymize) + if (forDisplay) { - AnonymizeFilePath(result.Path); + ReplaceCommonPathPrefix(result.Path, GetKnownFolderPath(FOLDERID_LocalAppData), "%LOCALAPPDATA%"); + ReplaceCommonPathPrefix(result.Path, GetKnownFolderPath(FOLDERID_RoamingAppData), "%APPDATA%"); } break; case PathName::SelfPackageRoot: @@ -633,14 +634,14 @@ namespace AppInstaller::Runtime return result; } - PathDetails GetPathDetailsFor(PathName path, bool anonymize) + PathDetails GetPathDetailsFor(PathName path, bool forDisplay) { PathDetails result; #ifndef WINGET_DISABLE_FOR_FUZZING if (IsRunningInPackagedContext()) { - result = GetPathDetailsForPackagedContext(path, anonymize); + result = GetPathDetailsForPackagedContext(path, forDisplay); } else #endif @@ -660,9 +661,9 @@ namespace AppInstaller::Runtime return result; } - std::filesystem::path GetPathTo(PathName path, bool anonymize) + std::filesystem::path GetPathTo(PathName path, bool forDisplay) { - PathDetails details = GetPathDetailsFor(path, anonymize); + PathDetails details = GetPathDetailsFor(path, forDisplay); if (details.Create) { From ea04d31c25eab1f59c590ff050841a54364cff90 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Wed, 5 Apr 2023 14:57:00 -0500 Subject: [PATCH 04/15] Tear out DefaultLogLocationForDisplay --- .../Public/AppInstallerRuntime.h | 2 -- src/AppInstallerCommonCore/Runtime.cpp | 30 +++++++++++-------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h index 28c8edfc97..0031b4febf 100644 --- a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h +++ b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h @@ -39,8 +39,6 @@ namespace AppInstaller::Runtime LocalState, // The default location where log files are located. DefaultLogLocation, - // The default location, anonymized using environment variables. - DefaultLogLocationForDisplay, // The location that standard type settings are stored. // In a packaged context, this returns a prepend value for the container name. StandardSettings, diff --git a/src/AppInstallerCommonCore/Runtime.cpp b/src/AppInstallerCommonCore/Runtime.cpp index 3ab4f0c262..04a7fe2e2c 100644 --- a/src/AppInstallerCommonCore/Runtime.cpp +++ b/src/AppInstallerCommonCore/Runtime.cpp @@ -485,7 +485,7 @@ namespace AppInstaller::Runtime } #ifndef WINGET_DISABLE_FOR_FUZZING - PathDetails GetPathDetailsForPackagedContext(PathName path, bool forDisplay) + PathDetails GetPathDetailsForPackagedContext(PathName path, bool forDisplay = false) { PathDetails result; @@ -504,12 +504,10 @@ namespace AppInstaller::Runtime result.Path.assign(appStorage.LocalFolder().Path().c_str()); break; case PathName::DefaultLogLocation: - case PathName::DefaultLogLocationForDisplay: // To enable UIF collection through Feedback hub, we must put our logs here. result.Path.assign(appStorage.LocalFolder().Path().c_str()); result.Path /= WINGET_DEFAULT_LOG_DIRECTORY; - - if (path == PathName::DefaultLogLocationForDisplay) + if (forDisplay) { ReplaceCommonPathPrefix(result.Path, GetKnownFolderPath(FOLDERID_LocalAppData), "%LOCALAPPDATA%"); } @@ -560,7 +558,7 @@ namespace AppInstaller::Runtime } #endif - PathDetails GetPathDetailsForUnpackagedContext(PathName path) + PathDetails GetPathDetailsForUnpackagedContext(PathName path, bool forDisplay = false) { PathDetails result; @@ -569,23 +567,31 @@ namespace AppInstaller::Runtime case PathName::Temp: case PathName::DefaultLogLocation: { - result.Path = GetPathToUserTemp(); + if (forDisplay) + { + result.Path.assign("%TEMP%"); + } + else + { + result.Path = GetPathToUserTemp(); + } + result.Path /= s_DefaultTempDirectory; result.Path /= GetRuntimePathStateName(); + if (path == PathName::Temp) { result.SetOwner(ACEPrincipal::CurrentUser); result.ACL[ACEPrincipal::System] = ACEPermissions::All; result.ACL[ACEPrincipal::Admins] = ACEPermissions::All; } + + if (path == PathName::DefaultLogLocation && forDisplay) + { + result.Create = false; + } } break; - case PathName::DefaultLogLocationForDisplay: - result.Path.assign("%TEMP%"); - result.Path /= s_DefaultTempDirectory; - result.Path /= GetRuntimePathStateName(); - result.Create = false; - break; case PathName::LocalState: result.Path = GetPathToAppDataDir(s_AppDataDir_State); result.Path /= GetRuntimePathStateName(); From e81ff61136f08079216a10760b19a6abf5e6685a Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Wed, 5 Apr 2023 14:58:36 -0500 Subject: [PATCH 05/15] Actually remove the function this time --- src/AppInstallerCommonCore/Filesystem.cpp | 7 ------- src/AppInstallerCommonCore/Public/winget/Filesystem.h | 4 ---- 2 files changed, 11 deletions(-) diff --git a/src/AppInstallerCommonCore/Filesystem.cpp b/src/AppInstallerCommonCore/Filesystem.cpp index 46b75b7762..e194710832 100644 --- a/src/AppInstallerCommonCore/Filesystem.cpp +++ b/src/AppInstallerCommonCore/Filesystem.cpp @@ -236,13 +236,6 @@ namespace AppInstaller::Filesystem return false; } - bool AnonymizeFilePath(std::filesystem::path& source) - { - bool replaced = ReplaceCommonPathPrefix(source, GetKnownFolderPath(FOLDERID_LocalAppData), "%LOCALAPPDATA%"); - replaced = ReplaceCommonPathPrefix(source, GetKnownFolderPath(FOLDERID_RoamingAppData), "%APPDATA%") && replaced; - return replaced; - } - std::filesystem::path GetKnownFolderPath(const KNOWNFOLDERID& id) { wil::unique_cotaskmem_string knownFolder = nullptr; diff --git a/src/AppInstallerCommonCore/Public/winget/Filesystem.h b/src/AppInstallerCommonCore/Public/winget/Filesystem.h index 3071e1eee2..0e202ace16 100644 --- a/src/AppInstallerCommonCore/Public/winget/Filesystem.h +++ b/src/AppInstallerCommonCore/Public/winget/Filesystem.h @@ -41,10 +41,6 @@ namespace AppInstaller::Filesystem // Returns true if replacement happened, false otherwise. bool ReplaceCommonPathPrefix(std::filesystem::path& source, const std::filesystem::path& prefix, std::string_view replacement); - // If the path begins with a common prefix for APPDATA or LOCALAPPDATA, replace it with the anonymized version - // Returns true if replacement happened, false otherwise. - bool AnonymizeFilePath(std::filesystem::path& source); - // Gets the path of a known folder. std::filesystem::path GetKnownFolderPath(const KNOWNFOLDERID& id); From da6bc6183d97d081fa287533a153efd8ad5ccc32 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Thu, 6 Apr 2023 09:41:12 -0500 Subject: [PATCH 06/15] Fix Path Entry --- src/AppInstallerCLICore/Commands/RootCommand.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp index 7c43657909..83903719ae 100644 --- a/src/AppInstallerCLICore/Commands/RootCommand.cpp +++ b/src/AppInstallerCLICore/Commands/RootCommand.cpp @@ -223,7 +223,7 @@ namespace AppInstaller::CLI info << Resource::String::Package(Runtime::GetPackageVersion()) << std::endl; }; - info << std::endl << Resource::String::Logs(Utility::LocIndView{ Runtime::GetPathTo(Runtime::PathName::DefaultLogLocationForDisplay).u8string() }) << std::endl; + info << std::endl << Resource::String::Logs(Utility::LocIndView{ Runtime::GetPathTo(Runtime::PathName::DefaultLogLocation, true).u8string() }) << std::endl; info << std::endl << Resource::String::UserSettings(Utility::LocIndView{ UserSettings::SettingsFilePath(true).u8string() }) << std::endl; info << std::endl; From 3b4a3de7f683acd40173801386e4ce82ed0238ca Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Thu, 6 Apr 2023 09:43:10 -0500 Subject: [PATCH 07/15] Alphabetize new resource strings --- src/AppInstallerCLICore/Resources.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h index a3481c26be..21b0336fd5 100644 --- a/src/AppInstallerCLICore/Resources.h +++ b/src/AppInstallerCLICore/Resources.h @@ -312,14 +312,14 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(PortableHashMismatchOverrideRequired); WINGET_DEFINE_RESOURCE_STRINGID(PortableAliasAdded); WINGET_DEFINE_RESOURCE_STRINGID(PortableDirectoriesHeader); + WINGET_DEFINE_RESOURCE_STRINGID(PortableInstallFailed); WINGET_DEFINE_RESOURCE_STRINGID(PortableLinksMachine); WINGET_DEFINE_RESOURCE_STRINGID(PortableLinksUser); - WINGET_DEFINE_RESOURCE_STRINGID(PortableRootUser); - WINGET_DEFINE_RESOURCE_STRINGID(PortableRoot64); - WINGET_DEFINE_RESOURCE_STRINGID(PortableRoot86); - WINGET_DEFINE_RESOURCE_STRINGID(PortableInstallFailed); WINGET_DEFINE_RESOURCE_STRINGID(PortablePackageAlreadyExists); WINGET_DEFINE_RESOURCE_STRINGID(PortableRegistryCollisionOverridden); + WINGET_DEFINE_RESOURCE_STRINGID(PortableRoot64); + WINGET_DEFINE_RESOURCE_STRINGID(PortableRoot86); + WINGET_DEFINE_RESOURCE_STRINGID(PortableRootUser); WINGET_DEFINE_RESOURCE_STRINGID(PositionArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(PreserveArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(PressEnterToContinue); From dd2f348c4e877dc8d2d6e62a536d2ee385c0259f Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Thu, 6 Apr 2023 09:43:58 -0500 Subject: [PATCH 08/15] Simplify Conditional --- src/AppInstallerCommonCore/Runtime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AppInstallerCommonCore/Runtime.cpp b/src/AppInstallerCommonCore/Runtime.cpp index 04a7fe2e2c..ef4eee2ed8 100644 --- a/src/AppInstallerCommonCore/Runtime.cpp +++ b/src/AppInstallerCommonCore/Runtime.cpp @@ -586,7 +586,7 @@ namespace AppInstaller::Runtime result.ACL[ACEPrincipal::Admins] = ACEPermissions::All; } - if (path == PathName::DefaultLogLocation && forDisplay) + if (forDisplay) { result.Create = false; } From 33263e8623df67f535d96f2bff46ba263e151681 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Thu, 6 Apr 2023 21:22:47 -0500 Subject: [PATCH 09/15] Separate Case Statements --- src/AppInstallerCommonCore/Runtime.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/AppInstallerCommonCore/Runtime.cpp b/src/AppInstallerCommonCore/Runtime.cpp index ef4eee2ed8..fdc3c580b1 100644 --- a/src/AppInstallerCommonCore/Runtime.cpp +++ b/src/AppInstallerCommonCore/Runtime.cpp @@ -534,16 +534,17 @@ namespace AppInstaller::Runtime } break; case PathName::UserProfile: - case PathName::PortablePackageUserRoot: case PathName::PortablePackageMachineRootX64: case PathName::PortablePackageMachineRootX86: - case PathName::PortableLinksUserLocation: case PathName::PortableLinksMachineLocation: + result = GetPathDetailsCommon(path); + break; + case PathName::PortableLinksUserLocation: + case PathName::PortablePackageUserRoot: result = GetPathDetailsCommon(path); if (forDisplay) { ReplaceCommonPathPrefix(result.Path, GetKnownFolderPath(FOLDERID_LocalAppData), "%LOCALAPPDATA%"); - ReplaceCommonPathPrefix(result.Path, GetKnownFolderPath(FOLDERID_RoamingAppData), "%APPDATA%"); } break; case PathName::SelfPackageRoot: From b57ba9c73278644868a8d13c764eebf9e4cfbae0 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Thu, 6 Apr 2023 21:25:08 -0500 Subject: [PATCH 10/15] Combine redundant conditional --- src/AppInstallerCommonCore/Runtime.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/AppInstallerCommonCore/Runtime.cpp b/src/AppInstallerCommonCore/Runtime.cpp index fdc3c580b1..a350583692 100644 --- a/src/AppInstallerCommonCore/Runtime.cpp +++ b/src/AppInstallerCommonCore/Runtime.cpp @@ -571,6 +571,7 @@ namespace AppInstaller::Runtime if (forDisplay) { result.Path.assign("%TEMP%"); + result.Create = false; } else { @@ -586,11 +587,6 @@ namespace AppInstaller::Runtime result.ACL[ACEPrincipal::System] = ACEPermissions::All; result.ACL[ACEPrincipal::Admins] = ACEPermissions::All; } - - if (forDisplay) - { - result.Create = false; - } } break; case PathName::LocalState: From 5949c96aeee3ca2e5febde2060aefe2931b0d8d7 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Thu, 6 Apr 2023 21:27:03 -0500 Subject: [PATCH 11/15] Minimize whitespace changes --- src/AppInstallerCLICore/Commands/RootCommand.cpp | 1 + src/AppInstallerCommonCore/Runtime.cpp | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp index 83903719ae..ac860611c4 100644 --- a/src/AppInstallerCLICore/Commands/RootCommand.cpp +++ b/src/AppInstallerCLICore/Commands/RootCommand.cpp @@ -225,6 +225,7 @@ namespace AppInstaller::CLI info << std::endl << Resource::String::Logs(Utility::LocIndView{ Runtime::GetPathTo(Runtime::PathName::DefaultLogLocation, true).u8string() }) << std::endl; info << std::endl << Resource::String::UserSettings(Utility::LocIndView{ UserSettings::SettingsFilePath(true).u8string() }) << std::endl; + info << std::endl; Execution::TableOutput<2> links{ context.Reporter, { Resource::String::Links, {} } }; diff --git a/src/AppInstallerCommonCore/Runtime.cpp b/src/AppInstallerCommonCore/Runtime.cpp index a350583692..55a5d9b905 100644 --- a/src/AppInstallerCommonCore/Runtime.cpp +++ b/src/AppInstallerCommonCore/Runtime.cpp @@ -580,7 +580,6 @@ namespace AppInstaller::Runtime result.Path /= s_DefaultTempDirectory; result.Path /= GetRuntimePathStateName(); - if (path == PathName::Temp) { result.SetOwner(ACEPrincipal::CurrentUser); From c96a44b65b7d49e552c86d680faee5fa6f4bfde1 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Fri, 7 Apr 2023 12:08:27 -0500 Subject: [PATCH 12/15] Group all directories together --- .../Commands/RootCommand.cpp | 49 ++++++++++--------- src/AppInstallerCLICore/Resources.h | 2 +- .../Shared/Strings/en-us/winget.resw | 14 +++--- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp index ac860611c4..c6660902b6 100644 --- a/src/AppInstallerCLICore/Commands/RootCommand.cpp +++ b/src/AppInstallerCLICore/Commands/RootCommand.cpp @@ -127,15 +127,31 @@ namespace AppInstaller::CLI adminSettingsTable.Complete(); } - void OutputPortableDirectories(Execution::Context& context) + void OutputKeyDirectories(Execution::Context& context) { - Execution::TableOutput<2> portableRoots{ context.Reporter, { Resource::String::PortableDirectoriesHeader, {} } }; - portableRoots.OutputLine({ Resource::LocString{ Resource::String::PortableLinksUser }, Runtime::GetPathTo(Runtime::PathName::PortableLinksUserLocation, true).string() }); - portableRoots.OutputLine({ Resource::LocString{ Resource::String::PortableLinksMachine }, Runtime::GetPathTo(Runtime::PathName::PortableLinksMachineLocation, true).string() }); - portableRoots.OutputLine({ Resource::LocString{ Resource::String::PortableRootUser }, Runtime::GetPathTo(Runtime::PathName::PortablePackageUserRoot, true).string() }); - portableRoots.OutputLine({ Resource::LocString{ Resource::String::PortableRoot64 }, Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX86, true).string() }); - portableRoots.OutputLine({ Resource::LocString{ Resource::String::PortableRoot86 }, Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX64, true).string() }); - portableRoots.Complete(); + Execution::TableOutput<2> keyDirectories{ context.Reporter, { Resource::String::KeyDirectoriesHeader, {} } }; + keyDirectories.OutputLine({ Resource::LocString{ Resource::String::Logs }, Runtime::GetPathTo(Runtime::PathName::DefaultLogLocation, true).u8string() }); + keyDirectories.OutputLine({ Resource::LocString{ Resource::String::UserSettings() }, UserSettings::SettingsFilePath(true).u8string() }); + keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableLinksUser }, Runtime::GetPathTo(Runtime::PathName::PortableLinksUserLocation, true).u8string() }); + keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableLinksMachine }, Runtime::GetPathTo(Runtime::PathName::PortableLinksMachineLocation, true).u8string() }); + keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableRootUser }, Runtime::GetPathTo(Runtime::PathName::PortablePackageUserRoot, true).u8string() }); + keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableRoot64 }, Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX86, true).u8string() }); + keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableRoot86 }, Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX64, true).u8string() }); + keyDirectories.Complete(); + context.Reporter.Info() << std::endl; + } + + void OutputLinks(Execution::Context& context) + { + Execution::TableOutput<2> links{ context.Reporter, { Resource::String::Links, {} } }; + + links.OutputLine({ Resource::LocString(Resource::String::PrivacyStatement).get(), "https://aka.ms/winget-privacy" }); + links.OutputLine({ Resource::LocString(Resource::String::LicenseAgreement).get(), "https://aka.ms/winget-license" }); + links.OutputLine({ Resource::LocString(Resource::String::ThirdPartSoftwareNotices).get(), "https://aka.ms/winget-3rdPartyNotice" }); + links.OutputLine({ Resource::LocString(Resource::String::MainHomepage).get(), "https://aka.ms/winget" }); + links.OutputLine({ Resource::LocString(Resource::String::WindowsStoreTerms).get(), "https://www.microsoft.com/en-us/storedocs/terms-of-sale" }); + + links.Complete(); context.Reporter.Info() << std::endl; } } @@ -223,23 +239,10 @@ namespace AppInstaller::CLI info << Resource::String::Package(Runtime::GetPackageVersion()) << std::endl; }; - info << std::endl << Resource::String::Logs(Utility::LocIndView{ Runtime::GetPathTo(Runtime::PathName::DefaultLogLocation, true).u8string() }) << std::endl; - info << std::endl << Resource::String::UserSettings(Utility::LocIndView{ UserSettings::SettingsFilePath(true).u8string() }) << std::endl; - - info << std::endl; - - Execution::TableOutput<2> links{ context.Reporter, { Resource::String::Links, {} } }; - - links.OutputLine({ Resource::LocString(Resource::String::PrivacyStatement).get(), "https://aka.ms/winget-privacy" }); - links.OutputLine({ Resource::LocString(Resource::String::LicenseAgreement).get(), "https://aka.ms/winget-license" }); - links.OutputLine({ Resource::LocString(Resource::String::ThirdPartSoftwareNotices).get(), "https://aka.ms/winget-3rdPartyNotice" }); - links.OutputLine({ Resource::LocString(Resource::String::MainHomepage).get(), "https://aka.ms/winget" }); - links.OutputLine({ Resource::LocString(Resource::String::WindowsStoreTerms).get(), "https://www.microsoft.com/en-us/storedocs/terms-of-sale" }); - - links.Complete(); info << std::endl; - OutputPortableDirectories(context); + OutputKeyDirectories(context); + OutputLinks(context); OutputGroupPolicies(context); OutputAdminSettings(context); } diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h index 21b0336fd5..945d573406 100644 --- a/src/AppInstallerCLICore/Resources.h +++ b/src/AppInstallerCLICore/Resources.h @@ -219,6 +219,7 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(InvalidJsonFile); WINGET_DEFINE_RESOURCE_STRINGID(InvalidNameError); WINGET_DEFINE_RESOURCE_STRINGID(InvalidPathToNestedInstaller); + WINGET_DEFINE_RESOURCE_STRINGID(KeyDirectoriesHeader); WINGET_DEFINE_RESOURCE_STRINGID(LicenseAgreement); WINGET_DEFINE_RESOURCE_STRINGID(Links); WINGET_DEFINE_RESOURCE_STRINGID(ListCommandLongDescription); @@ -311,7 +312,6 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(PortableHashMismatchOverridden); WINGET_DEFINE_RESOURCE_STRINGID(PortableHashMismatchOverrideRequired); WINGET_DEFINE_RESOURCE_STRINGID(PortableAliasAdded); - WINGET_DEFINE_RESOURCE_STRINGID(PortableDirectoriesHeader); WINGET_DEFINE_RESOURCE_STRINGID(PortableInstallFailed); WINGET_DEFINE_RESOURCE_STRINGID(PortableLinksMachine); WINGET_DEFINE_RESOURCE_STRINGID(PortableLinksUser); diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index 8c19f09641..a75269017c 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -775,8 +775,8 @@ They can be configured through the settings file 'winget settings'. Both local manifest and search query arguments are provided - Logs: {0} - {Locked="{0}"} Label displayed for diagnostic files containing information about the application use. {0} is a placeholder replaced by the logs directory path. + Logs + Label displayed for diagnostic files containing information about the application use. The installer is blocked by policy @@ -1402,9 +1402,9 @@ Please specify one of them using the --source option to proceed. Command line alias added: - - Portable Installation Directories - Header for a table detailing the user's configured directories for portable installs + + Winget Directories + Header for a table detailing the directories Winget uses for key operations like logging and portable installs Portable Links Directory (Machine) @@ -1599,8 +1599,8 @@ Please specify one of them using the --source option to proceed. Export settings - User Settings: {0} - {Locked="{0}"} Label displayed for the file containing the user settings. {0} is a placeholder replaced by the user settings file path. + User Settings + Label displayed for the file containing the user settings. Settings file couldn't load. Using default values. From 368c591ca39d69beaf1434e655a6037dbad7fe67 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Fri, 7 Apr 2023 12:14:30 -0500 Subject: [PATCH 13/15] Cleanup --- src/AppInstallerCLICore/Commands/RootCommand.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp index c6660902b6..6485f10e12 100644 --- a/src/AppInstallerCLICore/Commands/RootCommand.cpp +++ b/src/AppInstallerCLICore/Commands/RootCommand.cpp @@ -131,7 +131,7 @@ namespace AppInstaller::CLI { Execution::TableOutput<2> keyDirectories{ context.Reporter, { Resource::String::KeyDirectoriesHeader, {} } }; keyDirectories.OutputLine({ Resource::LocString{ Resource::String::Logs }, Runtime::GetPathTo(Runtime::PathName::DefaultLogLocation, true).u8string() }); - keyDirectories.OutputLine({ Resource::LocString{ Resource::String::UserSettings() }, UserSettings::SettingsFilePath(true).u8string() }); + keyDirectories.OutputLine({ Resource::LocString{ Resource::String::UserSettings }, UserSettings::SettingsFilePath(true).u8string() }); keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableLinksUser }, Runtime::GetPathTo(Runtime::PathName::PortableLinksUserLocation, true).u8string() }); keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableLinksMachine }, Runtime::GetPathTo(Runtime::PathName::PortableLinksMachineLocation, true).u8string() }); keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableRootUser }, Runtime::GetPathTo(Runtime::PathName::PortablePackageUserRoot, true).u8string() }); @@ -144,13 +144,11 @@ namespace AppInstaller::CLI void OutputLinks(Execution::Context& context) { Execution::TableOutput<2> links{ context.Reporter, { Resource::String::Links, {} } }; - - links.OutputLine({ Resource::LocString(Resource::String::PrivacyStatement).get(), "https://aka.ms/winget-privacy" }); - links.OutputLine({ Resource::LocString(Resource::String::LicenseAgreement).get(), "https://aka.ms/winget-license" }); - links.OutputLine({ Resource::LocString(Resource::String::ThirdPartSoftwareNotices).get(), "https://aka.ms/winget-3rdPartyNotice" }); - links.OutputLine({ Resource::LocString(Resource::String::MainHomepage).get(), "https://aka.ms/winget" }); - links.OutputLine({ Resource::LocString(Resource::String::WindowsStoreTerms).get(), "https://www.microsoft.com/en-us/storedocs/terms-of-sale" }); - + links.OutputLine({ Resource::LocString{ Resource::String::PrivacyStatement }, "https://aka.ms/winget-privacy" }); + links.OutputLine({ Resource::LocString{ Resource::String::LicenseAgreement }, "https://aka.ms/winget-license" }); + links.OutputLine({ Resource::LocString{ Resource::String::ThirdPartSoftwareNotices }, "https://aka.ms/winget-3rdPartyNotice" }); + links.OutputLine({ Resource::LocString{ Resource::String::MainHomepage }, "https://aka.ms/winget" }); + links.OutputLine({ Resource::LocString{ Resource::String::WindowsStoreTerms }, "https://www.microsoft.com/en-us/storedocs/terms-of-sale" }); links.Complete(); context.Reporter.Info() << std::endl; } From c685440ab6bb1096ce312efdd772b297e4e10943 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Fri, 7 Apr 2023 12:23:07 -0500 Subject: [PATCH 14/15] Put key in alphabetical spot --- .../Shared/Strings/en-us/winget.resw | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw index a75269017c..e17431b031 100644 --- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw +++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -319,6 +319,10 @@ They can be configured through the settings file 'winget settings'. Argument name was not recognized for the current command: '{0}' {Locked="{0}"} Error message displayed when the user provides an unrecognized command line argument name for the selected command. {0} is a placeholder replaced by the user's argument name input (e.g. '--example'). + + Winget Directories + Header for a table detailing the directories Winget uses for key operations like logging and portable installs + Locale to use (BCP47 format) {Locked="BCP47"} @@ -1402,10 +1406,6 @@ Please specify one of them using the --source option to proceed. Command line alias added: - - Winget Directories - Header for a table detailing the directories Winget uses for key operations like logging and portable installs - Portable Links Directory (Machine) From 87268f097cb10cb2dd3cfd28cc9024cbcce35087 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Fri, 7 Apr 2023 15:25:39 -0500 Subject: [PATCH 15/15] Only show x64 location on x64 systems --- src/AppInstallerCLICore/Commands/RootCommand.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp index 6485f10e12..a385fbcd4b 100644 --- a/src/AppInstallerCLICore/Commands/RootCommand.cpp +++ b/src/AppInstallerCLICore/Commands/RootCommand.cpp @@ -135,8 +135,11 @@ namespace AppInstaller::CLI keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableLinksUser }, Runtime::GetPathTo(Runtime::PathName::PortableLinksUserLocation, true).u8string() }); keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableLinksMachine }, Runtime::GetPathTo(Runtime::PathName::PortableLinksMachineLocation, true).u8string() }); keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableRootUser }, Runtime::GetPathTo(Runtime::PathName::PortablePackageUserRoot, true).u8string() }); - keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableRoot64 }, Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX86, true).u8string() }); - keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableRoot86 }, Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX64, true).u8string() }); + keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableRoot86 }, Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX86, true).u8string() }); + if (Utility::GetSystemArchitecture() == Utility::Architecture::X64 || Utility::GetSystemArchitecture() == Utility::Architecture::Arm64) + { + keyDirectories.OutputLine({ Resource::LocString{ Resource::String::PortableRoot64 }, Runtime::GetPathTo(Runtime::PathName::PortablePackageMachineRootX64, true).u8string() }); + } keyDirectories.Complete(); context.Reporter.Info() << std::endl; }