winget-cli

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

commit ef03b761ab03aee47a40cb47028fc5b3b2341420
parent 5d3193dfd664f8966a0193b7dddc520d0eae57d8
Author: JohnMcPMS <johnmcp@microsoft.com>
Date:   Thu, 22 Oct 2020 11:43:15 -0700

Move the default location for installer logs (#623)


Diffstat:
Mazure-pipelines.yml | 1+
Msrc/AppInstallerCLICore/Commands/RootCommand.cpp | 2++
Msrc/AppInstallerCLICore/Resources.h | 1+
Msrc/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.cpp | 12+++++++++++-
Msrc/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.h | 2+-
Msrc/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw | 4++++
Msrc/AppInstallerCLITests/WorkFlow.cpp | 17+++++++++++++++--
Msrc/AppInstallerCommonCore/FileLogger.cpp | 10++++++++++
Msrc/AppInstallerCommonCore/Public/AppInstallerFileLogger.h | 4++++
Msrc/AppInstallerCommonCore/Public/AppInstallerRuntime.h | 2++
Msrc/AppInstallerCommonCore/Runtime.cpp | 38+++++++++++++++++++++++++++++++++++++-
11 files changed, 88 insertions(+), 5 deletions(-)

diff --git a/azure-pipelines.yml b/azure-pipelines.yml @@ -219,6 +219,7 @@ jobs: /p:AppxBundle=Never /p:UapAppxPackageBuildMode=SideLoadOnly /p:AppxPackageSigningEnabled=false' + condition: succeededOrFailed() - task: PowerShell@2 displayName: Install Root Certificate diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp @@ -76,6 +76,8 @@ namespace AppInstaller::CLI info << Resource::String::Package << ": "_liv << Runtime::GetPackageVersion() << std::endl; }; + info << std::endl << Resource::String::Logs << ": "_liv << Runtime::GetPathTo(Runtime::PathName::DefaultLogLocationForDisplay).u8string() << std::endl; + info << std::endl; Execution::TableOutput<2> links{ context.Reporter, { Resource::String::Links, {} } }; diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h @@ -92,6 +92,7 @@ namespace AppInstaller::CLI::Resource WINGET_DEFINE_RESOURCE_STRINGID(ListCommandShortDescription); WINGET_DEFINE_RESOURCE_STRINGID(LocationArgumentDescription); WINGET_DEFINE_RESOURCE_STRINGID(LogArgumentDescription); + WINGET_DEFINE_RESOURCE_STRINGID(Logs); WINGET_DEFINE_RESOURCE_STRINGID(MainCopyrightNotice); WINGET_DEFINE_RESOURCE_STRINGID(MainHomepage); WINGET_DEFINE_RESOURCE_STRINGID(ManifestArgumentDescription); diff --git a/src/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.cpp b/src/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.cpp @@ -2,6 +2,7 @@ // Licensed under the MIT License. #include "pch.h" #include "ShellExecuteInstallerHandler.h" +#include "AppInstallerFileLogger.h" using namespace AppInstaller::CLI; using namespace AppInstaller::Utility; @@ -140,7 +141,16 @@ namespace AppInstaller::CLI::Workflow } else { - logPath = Utility::ConvertToUTF8(context.Get<Execution::Data::InstallerPath>().c_str()) + ".log"; + const auto& manifest = context.Get<Execution::Data::Manifest>(); + + auto path = Runtime::GetPathTo(Runtime::PathName::DefaultLogLocation); + path /= Logging::FileLogger::DefaultPrefix(); + path += Utility::ConvertToUTF16(manifest.Id + '.' + manifest.Version); + path += '-'; + path += Utility::GetCurrentTimeForFilename(); + path += Logging::FileLogger::DefaultExt(); + + logPath = path.u8string(); } if (Utility::FindAndReplace(installerArgs, std::string(ARG_TOKEN_LOGPATH), logPath)) diff --git a/src/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.h b/src/AppInstallerCLICore/Workflows/ShellExecuteInstallerHandler.h @@ -19,7 +19,7 @@ namespace AppInstaller::CLI::Workflow // Gets the installer args from the context. // Required Args: None - // Inputs: Installer, InstallerPath + // Inputs: Manifest?, Installer, InstallerPath // Outputs: InstallerArgs void GetInstallerArgs(Execution::Context& context); diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw @@ -718,4 +718,8 @@ They can be configured through the settings file 'winget settings'.</value> <data name="BothManifestAndSearchQueryProvided" xml:space="preserve"> <value>Both local manifest and search query args are provided</value> </data> + <data name="Logs" xml:space="preserve"> + <value>Logs</value> + <comment>Diagnostic files containing information about application use.</comment> + </data> </root> \ No newline at end of file diff --git a/src/AppInstallerCLITests/WorkFlow.cpp b/src/AppInstallerCLITests/WorkFlow.cpp @@ -21,6 +21,7 @@ #include <winget/LocIndependent.h> #include <winget/ManifestYamlParser.h> #include <Resources.h> +#include <AppInstallerFileLogger.h> using namespace winrt::Windows::Foundation; using namespace winrt::Windows::Management::Deployment; @@ -28,6 +29,7 @@ using namespace TestCommon; using namespace AppInstaller::CLI; using namespace AppInstaller::CLI::Execution; using namespace AppInstaller::CLI::Workflow; +using namespace AppInstaller::Logging; using namespace AppInstaller::Manifest; using namespace AppInstaller::Repository; using namespace AppInstaller::Utility; @@ -471,12 +473,15 @@ TEST_CASE("ShellExecuteHandlerInstallerArgs", "[InstallFlow][workflow]") TestContext context{ installOutput, std::cin }; // Default Msi type with no args passed in, no switches specified in manifest auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallerArgTest_Msi_NoSwitches.yaml")); + context.Add<Data::Manifest>(manifest); context.Add<Data::Installer>(manifest.Installers.at(0)); context.Add<Data::InstallerPath>(TestDataFile("AppInstallerTestExeInstaller.exe")); context << GetInstallerArgs; std::string installerArgs = context.Get<Data::InstallerArgs>(); REQUIRE(installerArgs.find("/passive") != std::string::npos); - REQUIRE(installerArgs.find("AppInstallerTestExeInstaller.exe.log") != std::string::npos); + REQUIRE(installerArgs.find(FileLogger::DefaultPrefix()) != std::string::npos); + REQUIRE(installerArgs.find(manifest.Id) != std::string::npos); + REQUIRE(installerArgs.find(manifest.Version) != std::string::npos); } { @@ -487,6 +492,7 @@ TEST_CASE("ShellExecuteHandlerInstallerArgs", "[InstallFlow][workflow]") context.Args.AddArg(Execution::Args::Type::Silent); context.Args.AddArg(Execution::Args::Type::Log, "MyLog.log"sv); context.Args.AddArg(Execution::Args::Type::InstallLocation, "MyDir"sv); + context.Add<Data::Manifest>(manifest); context.Add<Data::Installer>(manifest.Installers.at(0)); context << GetInstallerArgs; std::string installerArgs = context.Get<Data::InstallerArgs>(); @@ -503,6 +509,7 @@ TEST_CASE("ShellExecuteHandlerInstallerArgs", "[InstallFlow][workflow]") context.Args.AddArg(Execution::Args::Type::Silent); context.Args.AddArg(Execution::Args::Type::Log, "MyLog.log"sv); context.Args.AddArg(Execution::Args::Type::InstallLocation, "MyDir"sv); + context.Add<Data::Manifest>(manifest); context.Add<Data::Installer>(manifest.Installers.at(0)); context << GetInstallerArgs; std::string installerArgs = context.Get<Data::InstallerArgs>(); @@ -517,12 +524,15 @@ TEST_CASE("ShellExecuteHandlerInstallerArgs", "[InstallFlow][workflow]") TestContext context{ installOutput, std::cin }; // Default Inno type with no args passed in, no switches specified in manifest auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallerArgTest_Inno_NoSwitches.yaml")); + context.Add<Data::Manifest>(manifest); context.Add<Data::Installer>(manifest.Installers.at(0)); context.Add<Data::InstallerPath>(TestDataFile("AppInstallerTestExeInstaller.exe")); context << GetInstallerArgs; std::string installerArgs = context.Get<Data::InstallerArgs>(); REQUIRE(installerArgs.find("/SILENT") != std::string::npos); - REQUIRE(installerArgs.find("AppInstallerTestExeInstaller.exe.log") != std::string::npos); + REQUIRE(installerArgs.find(FileLogger::DefaultPrefix()) != std::string::npos); + REQUIRE(installerArgs.find(manifest.Id) != std::string::npos); + REQUIRE(installerArgs.find(manifest.Version) != std::string::npos); } { @@ -533,6 +543,7 @@ TEST_CASE("ShellExecuteHandlerInstallerArgs", "[InstallFlow][workflow]") context.Args.AddArg(Execution::Args::Type::Silent); context.Args.AddArg(Execution::Args::Type::Log, "MyLog.log"sv); context.Args.AddArg(Execution::Args::Type::InstallLocation, "MyDir"sv); + context.Add<Data::Manifest>(manifest); context.Add<Data::Installer>(manifest.Installers.at(0)); context << GetInstallerArgs; std::string installerArgs = context.Get<Data::InstallerArgs>(); @@ -549,6 +560,7 @@ TEST_CASE("ShellExecuteHandlerInstallerArgs", "[InstallFlow][workflow]") context.Args.AddArg(Execution::Args::Type::Silent); context.Args.AddArg(Execution::Args::Type::Log, "MyLog.log"sv); context.Args.AddArg(Execution::Args::Type::InstallLocation, "MyDir"sv); + context.Add<Data::Manifest>(manifest); context.Add<Data::Installer>(manifest.Installers.at(0)); context << GetInstallerArgs; std::string installerArgs = context.Get<Data::InstallerArgs>(); @@ -567,6 +579,7 @@ TEST_CASE("ShellExecuteHandlerInstallerArgs", "[InstallFlow][workflow]") context.Args.AddArg(Execution::Args::Type::Log, "MyLog.log"sv); context.Args.AddArg(Execution::Args::Type::InstallLocation, "MyDir"sv); context.Args.AddArg(Execution::Args::Type::Override, "/OverrideEverything"sv); + context.Add<Data::Manifest>(manifest); context.Add<Data::Installer>(manifest.Installers.at(0)); context << GetInstallerArgs; std::string installerArgs = context.Get<Data::InstallerArgs>(); diff --git a/src/AppInstallerCommonCore/FileLogger.cpp b/src/AppInstallerCommonCore/FileLogger.cpp @@ -44,6 +44,16 @@ namespace AppInstaller::Logging return "file :: "s + filePath.u8string(); } + std::string_view FileLogger::DefaultPrefix() + { + return s_fileLoggerDefaultFilePrefix; + } + + std::string_view FileLogger::DefaultExt() + { + return s_fileLoggerDefaultFileExt; + } + std::string FileLogger::GetName() const { return m_name; diff --git a/src/AppInstallerCommonCore/Public/AppInstallerFileLogger.h b/src/AppInstallerCommonCore/Public/AppInstallerFileLogger.h @@ -6,6 +6,7 @@ #include <filesystem> #include <fstream> #include <string> +#include <string_view> namespace AppInstaller::Logging { @@ -24,6 +25,9 @@ namespace AppInstaller::Logging static std::string GetNameForPath(const std::filesystem::path& filePath); + static std::string_view DefaultPrefix(); + static std::string_view DefaultExt(); + // ILogger virtual std::string GetName() const override; diff --git a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h @@ -32,6 +32,8 @@ 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 @@ -231,9 +231,41 @@ namespace AppInstaller::Runtime result.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.assign(appStorage.LocalFolder().Path().c_str()); result /= WINGET_DEFAULT_LOG_DIRECTORY; + + if (path == PathName::DefaultLogLocationForDisplay) + { + std::filesystem::path localAppData = GetKnownFolderPath(FOLDERID_LocalAppData); + + auto ladItr = localAppData.begin(); + auto resultItr = result.begin(); + + while (ladItr != localAppData.end() && resultItr != result.end()) + { + if (*ladItr != *resultItr) + { + break; + } + + ++ladItr; + ++resultItr; + } + + if (ladItr == localAppData.end()) + { + localAppData.assign("%LOCALAPPDATA%"); + + for (;resultItr != result.end(); ++resultItr) + { + localAppData /= *resultItr; + } + + result = std::move(localAppData); + } + } break; case PathName::StandardSettings: create = false; @@ -265,7 +297,11 @@ namespace AppInstaller::Runtime result /= s_DefaultTempDirectory; } - break; + break; + case PathName::DefaultLogLocationForDisplay: + result.assign("%TEMP%"); + result /= s_DefaultTempDirectory; + break; case PathName::LocalState: result = GetPathToAppDataDir(s_AppDataDir_State); break;