winget-cli

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

commit 1e35cefb75618ab9ee3b7fe02aa9d66ba3d8345a
parent 9db7d636782350ad2373120f04296947a3d27b1e
Author: JohnMcPMS <johnmcp@microsoft.com>
Date:   Thu,  2 Jan 2020 16:49:44 -0800

Add logging infra and logs to existing code (#17)


Diffstat:
Msrc/AppInstallerCLI.sln | 45++++++++++++++++++++-------------------------
Msrc/AppInstallerCLI/AppInstallerCLI.vcxproj | 3+++
Msrc/AppInstallerCLI/main.cpp | 2+-
Msrc/AppInstallerCLICore/AppInstallerCLICore.vcxproj | 22+++++++++++-----------
Msrc/AppInstallerCLICore/Command.cpp | 55++++++++++++++++++++++++++++---------------------------
Msrc/AppInstallerCLICore/Command.h | 42+++++++++++++++++++++---------------------
Msrc/AppInstallerCLICore/Commands/DescribeCommand.cpp | 12++++++------
Msrc/AppInstallerCLICore/Commands/DescribeCommand.h | 6+++---
Msrc/AppInstallerCLICore/Commands/InstallCommand.cpp | 10+++++-----
Msrc/AppInstallerCLICore/Commands/InstallCommand.h | 6+++---
Msrc/AppInstallerCLICore/Commands/RootCommand.cpp | 8++++----
Msrc/AppInstallerCLICore/Commands/RootCommand.h | 6+++---
Msrc/AppInstallerCLICore/Common.h | 4++--
Msrc/AppInstallerCLICore/Core.cpp | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/AppInstallerCLICore/Invocation.h | 49+++++++++++++++++++++++++++++--------------------
Msrc/AppInstallerCLICore/Public/AppInstallerCLICore.h | 10+++++++---
Msrc/AppInstallerCLICore/packages.config | 1+
Msrc/AppInstallerCLICore/pch.h | 9++++++---
Msrc/AppInstallerCLITests/AppInstallerCLITests.vcxproj | 11+++++++----
Msrc/AppInstallerCLITests/main.cpp | 9+++++++++
Asrc/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj | 208+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/AppInstallerCommonCore/AppInstallerLogging.cpp | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/AppInstallerCommonCore/AppInstallerStrings.cpp | 38++++++++++++++++++++++++++++++++++++++
Asrc/AppInstallerCommonCore/AppInstallerTelemetry.cpp | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/AppInstallerCommonCore/DateTime.cpp | 29+++++++++++++++++++++++++++++
Asrc/AppInstallerCommonCore/DateTime.h | 14++++++++++++++
Asrc/AppInstallerCommonCore/FileLogger.cpp | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/AppInstallerCommonCore/FileLogger.h | 37+++++++++++++++++++++++++++++++++++++
Asrc/AppInstallerCommonCore/PropertySheet.props | 17+++++++++++++++++
Asrc/AppInstallerCommonCore/Public/AppInstallerLogging.h | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/AppInstallerCommonCore/Public/AppInstallerRuntime.h | 14++++++++++++++
Asrc/AppInstallerCommonCore/Public/AppInstallerStrings.h | 15+++++++++++++++
Asrc/AppInstallerCommonCore/Public/AppInstallerTelemetry.h | 43+++++++++++++++++++++++++++++++++++++++++++
Asrc/AppInstallerCommonCore/Runtime.cpp | 39+++++++++++++++++++++++++++++++++++++++
Rsrc/Telemetry/MicrosoftTelemetry.h -> src/AppInstallerCommonCore/Telemetry/MicrosoftTelemetry.h | 0
Rsrc/Telemetry/TraceLogging.cpp -> src/AppInstallerCommonCore/Telemetry/TraceLogging.cpp | 0
Rsrc/Telemetry/TraceLogging.h -> src/AppInstallerCommonCore/Telemetry/TraceLogging.h | 0
Rsrc/Telemetry/WinEventLogLevels.h -> src/AppInstallerCommonCore/Telemetry/WinEventLogLevels.h | 0
Asrc/AppInstallerCommonCore/packages.config | 6++++++
Asrc/AppInstallerCommonCore/pch.cpp | 3+++
Asrc/AppInstallerCommonCore/pch.h | 23+++++++++++++++++++++++
Msrc/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj | 20+++++++++-----------
Msrc/AppInstallerRepositoryCore/Microsoft/SQLiteIndex.cpp | 39++++++++++++++++++++++++++++++---------
Msrc/AppInstallerRepositoryCore/Microsoft/SQLiteIndex.h | 8++++----
Msrc/AppInstallerRepositoryCore/Microsoft/Schema/Version.cpp | 5+++++
Msrc/AppInstallerRepositoryCore/Microsoft/Schema/Version.h | 3+++
Msrc/AppInstallerRepositoryCore/SQLiteWrapper.cpp | 71++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/AppInstallerRepositoryCore/SQLiteWrapper.h | 39++++++++++++++++++++-------------------
Msrc/AppInstallerRepositoryCore/pch.h | 6+++---
Dsrc/Telemetry/Telemetry.vcxitems | 27---------------------------
Dsrc/Telemetry/TelemetryWrapper.cpp | 41-----------------------------------------
Dsrc/Telemetry/TelemetryWrapper.h | 21---------------------
53 files changed, 1294 insertions(+), 340 deletions(-)

diff --git a/src/AppInstallerCLI.sln b/src/AppInstallerCLI.sln @@ -8,9 +8,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppInstallerCLI", "AppInsta EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppInstallerCLICore", "AppInstallerCLICore\AppInstallerCLICore.vcxproj", "{1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{60618CAC-2995-4DF9-9914-45C6FC02C995}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Telemetry", "Telemetry\Telemetry.vcxitems", "{4B988559-DDBD-4456-9300-0C3AAD12C466}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "External - Do Not Modify", "External - Do Not Modify", "{60618CAC-2995-4DF9-9914-45C6FC02C995}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppInstallerRepositoryCore", "AppInstallerRepositoryCore\AppInstallerRepositoryCore.vcxproj", "{5EB88068-5FB9-4E69-89B2-72DBC5E068F9}" EndProject @@ -27,30 +25,24 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppInstallerCLITests", "App EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "YamlCppLib", "YamlCppLib\YamlCppLib.vcxproj", "{8BB94BB8-374F-4294-BCA1-C7811514A6B7}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppInstallerCommonCore", "AppInstallerCommonCore\AppInstallerCommonCore.vcxproj", "{5890D6ED-7C3B-40F3-B436-B54F640D9E65}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution - Telemetry\Telemetry.vcxitems*{1c6e0108-2860-4b17-9f7e-fa5c6c1f3d3d}*SharedItemsImports = 4 - Telemetry\Telemetry.vcxitems*{4b988559-ddbd-4456-9300-0c3aad12c466}*SharedItemsImports = 9 catch2\catch2.vcxitems*{5295e21e-9868-4de2-a177-fbb97b36579b}*SharedItemsImports = 9 - Telemetry\Telemetry.vcxitems*{5eb88068-5fb9-4e69-89b2-72dbc5e068f9}*SharedItemsImports = 4 catch2\catch2.vcxitems*{89b1aab4-2bbc-4b65-9ed7-a01d5cf88230}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6AA3791A-0713-4548-A357-87A323E7AC3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6AA3791A-0713-4548-A357-87A323E7AC3A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6AA3791A-0713-4548-A357-87A323E7AC3A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU {6AA3791A-0713-4548-A357-87A323E7AC3A}.Debug|ARM.ActiveCfg = Debug|ARM {6AA3791A-0713-4548-A357-87A323E7AC3A}.Debug|ARM.Build.0 = Debug|ARM {6AA3791A-0713-4548-A357-87A323E7AC3A}.Debug|ARM.Deploy.0 = Debug|ARM @@ -63,9 +55,6 @@ Global {6AA3791A-0713-4548-A357-87A323E7AC3A}.Debug|x86.ActiveCfg = Debug|x86 {6AA3791A-0713-4548-A357-87A323E7AC3A}.Debug|x86.Build.0 = Debug|x86 {6AA3791A-0713-4548-A357-87A323E7AC3A}.Debug|x86.Deploy.0 = Debug|x86 - {6AA3791A-0713-4548-A357-87A323E7AC3A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6AA3791A-0713-4548-A357-87A323E7AC3A}.Release|Any CPU.Build.0 = Release|Any CPU - {6AA3791A-0713-4548-A357-87A323E7AC3A}.Release|Any CPU.Deploy.0 = Release|Any CPU {6AA3791A-0713-4548-A357-87A323E7AC3A}.Release|ARM.ActiveCfg = Release|ARM {6AA3791A-0713-4548-A357-87A323E7AC3A}.Release|ARM.Build.0 = Release|ARM {6AA3791A-0713-4548-A357-87A323E7AC3A}.Release|ARM.Deploy.0 = Release|ARM @@ -78,7 +67,6 @@ Global {6AA3791A-0713-4548-A357-87A323E7AC3A}.Release|x86.ActiveCfg = Release|x86 {6AA3791A-0713-4548-A357-87A323E7AC3A}.Release|x86.Build.0 = Release|x86 {6AA3791A-0713-4548-A357-87A323E7AC3A}.Release|x86.Deploy.0 = Release|x86 - {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Debug|Any CPU.ActiveCfg = Debug|Win32 {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Debug|ARM.ActiveCfg = Debug|ARM {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Debug|ARM.Build.0 = Debug|ARM {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -87,7 +75,6 @@ Global {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Debug|x64.Build.0 = Debug|x64 {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Debug|x86.ActiveCfg = Debug|Win32 {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Debug|x86.Build.0 = Debug|Win32 - {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Release|Any CPU.ActiveCfg = Release|Win32 {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Release|ARM.ActiveCfg = Release|ARM {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Release|ARM.Build.0 = Release|ARM {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -96,7 +83,6 @@ Global {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Release|x64.Build.0 = Release|x64 {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Release|x86.ActiveCfg = Release|Win32 {5B6F90DF-FD19-4BAE-83D9-24DAD128E777}.Release|x86.Build.0 = Release|Win32 - {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Debug|Any CPU.ActiveCfg = Debug|Win32 {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Debug|ARM.ActiveCfg = Debug|ARM {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Debug|ARM.Build.0 = Debug|ARM {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -105,7 +91,6 @@ Global {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Debug|x64.Build.0 = Debug|x64 {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Debug|x86.ActiveCfg = Debug|Win32 {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Debug|x86.Build.0 = Debug|Win32 - {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Release|Any CPU.ActiveCfg = Release|Win32 {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Release|ARM.ActiveCfg = Release|ARM {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Release|ARM.Build.0 = Release|ARM {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -114,7 +99,6 @@ Global {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Release|x64.Build.0 = Release|x64 {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Release|x86.ActiveCfg = Release|Win32 {1C6E0108-2860-4B17-9F7E-FA5C6C1F3D3D}.Release|x86.Build.0 = Release|Win32 - {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Debug|Any CPU.ActiveCfg = Debug|Win32 {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Debug|ARM.ActiveCfg = Debug|ARM {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Debug|ARM.Build.0 = Debug|ARM {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -123,7 +107,6 @@ Global {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Debug|x64.Build.0 = Debug|x64 {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Debug|x86.ActiveCfg = Debug|Win32 {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Debug|x86.Build.0 = Debug|Win32 - {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Release|Any CPU.ActiveCfg = Release|Win32 {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Release|ARM.ActiveCfg = Release|ARM {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Release|ARM.Build.0 = Release|ARM {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -132,21 +115,18 @@ Global {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Release|x64.Build.0 = Release|x64 {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Release|x86.ActiveCfg = Release|Win32 {5EB88068-5FB9-4E69-89B2-72DBC5E068F9}.Release|x86.Build.0 = Release|Win32 - {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Debug|Any CPU.ActiveCfg = Debug|Win32 {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Debug|ARM.ActiveCfg = Debug|Win32 {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Debug|ARM64.ActiveCfg = Debug|Win32 {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Debug|x64.ActiveCfg = Debug|x64 {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Debug|x64.Build.0 = Debug|x64 {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Debug|x86.ActiveCfg = Debug|Win32 {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Debug|x86.Build.0 = Debug|Win32 - {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Release|Any CPU.ActiveCfg = Release|Win32 {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Release|ARM.ActiveCfg = Release|Win32 {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Release|ARM64.ActiveCfg = Release|Win32 {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Release|x64.ActiveCfg = Release|x64 {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Release|x64.Build.0 = Release|x64 {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Release|x86.ActiveCfg = Release|Win32 {89B1AAB4-2BBC-4B65-9ED7-A01D5CF88230}.Release|x86.Build.0 = Release|Win32 - {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Debug|Any CPU.ActiveCfg = Debug|Win32 {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Debug|ARM.ActiveCfg = Debug|ARM {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Debug|ARM.Build.0 = Debug|ARM {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Debug|ARM64.ActiveCfg = Debug|ARM64 @@ -155,7 +135,6 @@ Global {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Debug|x64.Build.0 = Debug|x64 {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Debug|x86.ActiveCfg = Debug|Win32 {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Debug|x86.Build.0 = Debug|Win32 - {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Release|Any CPU.ActiveCfg = Release|Win32 {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Release|ARM.ActiveCfg = Release|ARM {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Release|ARM.Build.0 = Release|ARM {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Release|ARM64.ActiveCfg = Release|ARM64 @@ -164,13 +143,29 @@ Global {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Release|x64.Build.0 = Release|x64 {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Release|x86.ActiveCfg = Release|Win32 {8BB94BB8-374F-4294-BCA1-C7811514A6B7}.Release|x86.Build.0 = Release|Win32 + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Debug|ARM.ActiveCfg = Debug|ARM + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Debug|ARM.Build.0 = Debug|ARM + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Debug|ARM64.Build.0 = Debug|ARM64 + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Debug|x64.ActiveCfg = Debug|x64 + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Debug|x64.Build.0 = Debug|x64 + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Debug|x86.ActiveCfg = Debug|Win32 + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Debug|x86.Build.0 = Debug|Win32 + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Release|ARM.ActiveCfg = Release|ARM + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Release|ARM.Build.0 = Release|ARM + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Release|ARM64.ActiveCfg = Release|ARM64 + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Release|ARM64.Build.0 = Release|ARM64 + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Release|x64.ActiveCfg = Release|x64 + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Release|x64.Build.0 = Release|x64 + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Release|x86.ActiveCfg = Release|Win32 + {5890D6ED-7C3B-40F3-B436-B54F640D9E65}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {4B988559-DDBD-4456-9300-0C3AAD12C466} = {60618CAC-2995-4DF9-9914-45C6FC02C995} {5295E21E-9868-4DE2-A177-FBB97B36579B} = {60618CAC-2995-4DF9-9914-45C6FC02C995} + {8BB94BB8-374F-4294-BCA1-C7811514A6B7} = {60618CAC-2995-4DF9-9914-45C6FC02C995} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {B6FDB70C-A751-422C-ACD1-E35419495857} diff --git a/src/AppInstallerCLI/AppInstallerCLI.vcxproj b/src/AppInstallerCLI/AppInstallerCLI.vcxproj @@ -167,6 +167,9 @@ <Project>{1c6e0108-2860-4b17-9f7e-fa5c6c1f3d3d}</Project> <Private>false</Private> </ProjectReference> + <ProjectReference Include="..\AppInstallerCommonCore\AppInstallerCommonCore.vcxproj"> + <Project>{5890d6ed-7c3b-40f3-b436-b54f640d9e65}</Project> + </ProjectReference> <ProjectReference Include="..\AppInstallerRepositoryCore\AppInstallerRepositoryCore.vcxproj"> <Project>{5eb88068-5fb9-4e69-89b2-72dbc5e068f9}</Project> </ProjectReference> diff --git a/src/AppInstallerCLI/main.cpp b/src/AppInstallerCLI/main.cpp @@ -4,5 +4,5 @@ int wmain(int argc, wchar_t const** argv) { - return CLICoreMain(argc, argv); + return AppInstaller::CLI::CoreMain(argc, argv); } diff --git a/src/AppInstallerCLICore/AppInstallerCLICore.vcxproj b/src/AppInstallerCLICore/AppInstallerCLICore.vcxproj @@ -68,9 +68,7 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> - <ImportGroup Label="Shared"> - <Import Project="..\Telemetry\Telemetry.vcxitems" Label="Shared" /> - </ImportGroup> + <ImportGroup Label="Shared" /> <ImportGroup Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> @@ -124,9 +122,9 @@ <ClCompile> <Optimization>Disabled</Optimization> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions);CLICOREDLLBUILD</PreprocessorDefinitions> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ClCompile> <Link> <GenerateWindowsMetadata>false</GenerateWindowsMetadata> @@ -138,7 +136,7 @@ <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'"> <ClCompile> <PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions);CLICOREDLLBUILD</PreprocessorDefinitions> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ClCompile> <Link> <SubSystem Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Windows</SubSystem> @@ -150,10 +148,10 @@ <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions);CLICOREDLLBUILD</PreprocessorDefinitions> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ClCompile> <Link> <EnableCOMDATFolding>true</EnableCOMDATFolding> @@ -194,6 +192,7 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> <Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.targets')" /> + <Import Project="$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.191107.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.191107.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" /> </ImportGroup> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <PropertyGroup> @@ -201,5 +200,6 @@ </PropertyGroup> <Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.props'))" /> <Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.targets'))" /> + <Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.191107.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.191107.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" /> </Target> </Project> \ No newline at end of file diff --git a/src/AppInstallerCLICore/Command.cpp b/src/AppInstallerCLICore/Command.cpp @@ -6,20 +6,20 @@ namespace AppInstaller::CLI { - void Command::OutputIntroHeader(std::wostream& out) const + void Command::OutputIntroHeader(std::ostream& out) const { - out << L"AppInstaller Command Line" << std::endl; - out << L"(c) 2019 Microsoft Corporation" << std::endl; + out << "AppInstaller Command Line" << std::endl; + out << "(c) 2019 Microsoft Corporation" << std::endl; } - void Command::OutputHelp(std::wostream& out, const CommandException* exception) const + void Command::OutputHelp(std::ostream& out, const CommandException* exception) const { OutputIntroHeader(out); out << std::endl; if (exception) { - out << exception->Message() << L" : " << exception->Param() << std::endl; + out << exception->Message() << " : '" << exception->Param() << '\'' << std::endl; out << std::endl; } @@ -32,27 +32,27 @@ namespace AppInstaller::CLI auto commands = GetCommands(); if (!commands.empty()) { - out << LOCME(L"The following commands are available:") << std::endl; + out << LOCME("The following commands are available:") << std::endl; out << std::endl; for (const auto& command : commands) { - out << L" " << command->Name() << std::endl; - out << L" " << command->ShortDescription() << std::endl; + out << " " << command->Name() << std::endl; + out << " " << command->ShortDescription() << std::endl; } out << std::endl; - out << LOCME(L"For more details on a specific command, pass it the help argument.") << L" [" << APPINSTALLER_CLI_HELP_ARGUMENT << L"]" << std::endl; + out << LOCME("For more details on a specific command, pass it the help argument.") << " [" << APPINSTALLER_CLI_HELP_ARGUMENT << "]" << std::endl; } else { - out << LOCME(L"The following arguments are available:") << std::endl; + out << LOCME("The following arguments are available:") << std::endl; out << std::endl; for (const auto& arg : GetArguments()) { - out << L" " << arg.Name() << std::endl; - out << L" " << arg.Description() << std::endl; + out << " " << arg.Name() << std::endl; + out << " " << arg.Description() << std::endl; } } } @@ -60,7 +60,7 @@ namespace AppInstaller::CLI std::unique_ptr<Command> Command::FindInvokedCommand(Invocation& inv) const { auto itr = inv.begin(); - if (itr == inv.end() || **itr == APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_CHAR) + if (itr == inv.end() || (*itr)[0] == APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_CHAR) { // No more command arguments to check, so no command to find return {}; @@ -73,12 +73,11 @@ namespace AppInstaller::CLI return {}; } - std::wstring arg = *itr; - for (auto& command : commands) { - if (arg == command->Name()) + if (*itr == command->Name()) { + AICLI_LOG(CLI, Info, << "Found subcommand: " << *itr); inv.consume(itr); std::unique_ptr<Command> subcommand = command->FindInvokedCommand(inv); // If we found a subcommand, return it. Otherwise, this is the one. @@ -86,7 +85,7 @@ namespace AppInstaller::CLI } } - throw CommandException(LOCME(L"Unrecognized command"), arg); + throw CommandException(LOCME("Unrecognized command"), *itr); } void Command::ParseArguments(Invocation& inv) const @@ -96,7 +95,7 @@ namespace AppInstaller::CLI for (auto incomingArgsItr = inv.begin(); incomingArgsItr != inv.end(); ++incomingArgsItr) { - if (**incomingArgsItr != APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_CHAR) + if ((*incomingArgsItr)[0] != APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_CHAR) { // Positional argument, find the next appropriate one if the current itr isn't one or has hit its limit. if (positionalSearchItr != definedArgs.end() && @@ -107,7 +106,7 @@ namespace AppInstaller::CLI if (positionalSearchItr == definedArgs.end()) { - throw CommandException(LOCME(L"Found a positional argument when none was expected"), *incomingArgsItr); + throw CommandException(LOCME("Found a positional argument when none was expected"), *incomingArgsItr); } inv.AddArg(positionalSearchItr->Name(), *incomingArgsItr); @@ -116,7 +115,7 @@ namespace AppInstaller::CLI { // This is an arg name, find it and process its value if needed. // Skip the name identifier char. - std::wstring argName = *incomingArgsItr + 1; + std::string argName = incomingArgsItr->substr(1); bool argFound = false; for (const auto& arg : definedArgs) @@ -132,7 +131,7 @@ namespace AppInstaller::CLI ++incomingArgsItr; if (incomingArgsItr == inv.end()) { - throw CommandException(LOCME(L"Argument value required, but none found"), *incomingArgsItr); + throw CommandException(LOCME("Argument value required, but none found"), *incomingArgsItr); } inv.AddArg(arg.Name(), *incomingArgsItr); } @@ -147,7 +146,7 @@ namespace AppInstaller::CLI } else if (!argFound) { - throw CommandException(LOCME(L"Argument name was not recognized for the current command"), *incomingArgsItr); + throw CommandException(LOCME("Argument name was not recognized for the current command"), *incomingArgsItr); } } } @@ -165,18 +164,19 @@ namespace AppInstaller::CLI { if (arg.Required() && !inv.Contains(arg.Name())) { - throw CommandException(LOCME(L"Required argument not provided"), arg.Name()); + throw CommandException(LOCME("Required argument not provided"), arg.Name()); } if (arg.Limit() < inv.GetCount(arg.Name())) { - throw CommandException(LOCME(L"Argument provided more times than allowed"), arg.Name()); + throw CommandException(LOCME("Argument provided more times than allowed"), arg.Name()); } } } - void Command::Execute(Invocation& inv, std::wostream& out) const + void Command::Execute(Invocation& inv, std::ostream& out) const { + AICLI_LOG(CLI, Info, << "Executing command: " << Name()); if (inv.Contains(APPINSTALLER_CLI_HELP_ARGUMENT_TEXT_STRING)) { OutputHelp(out); @@ -187,8 +187,9 @@ namespace AppInstaller::CLI } } - void Command::ExecuteInternal(Invocation&, std::wostream& out) const + void Command::ExecuteInternal(Invocation&, std::ostream& out) const { - out << LOCME(L"Oops, we forgot to do this...") << std::endl; + out << LOCME("Oops, we forgot to do this...") << std::endl; + THROW_HR(E_NOTIMPL); } } diff --git a/src/AppInstallerCLICore/Command.h b/src/AppInstallerCLICore/Command.h @@ -11,24 +11,24 @@ #include "Common.h" #include "Invocation.h" -#define APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_CHAR L'-' -#define APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_STRING L"-" -#define APPINSTALLER_CLI_HELP_ARGUMENT_TEXT_CHAR L'?' -#define APPINSTALLER_CLI_HELP_ARGUMENT_TEXT_STRING L"?" +#define APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_CHAR '-' +#define APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_STRING "-" +#define APPINSTALLER_CLI_HELP_ARGUMENT_TEXT_CHAR '?' +#define APPINSTALLER_CLI_HELP_ARGUMENT_TEXT_STRING "?" #define APPINSTALLER_CLI_HELP_ARGUMENT APPINSTALLER_CLI_ARGUMENT_IDENTIFIER_STRING APPINSTALLER_CLI_HELP_ARGUMENT_TEXT_STRING namespace AppInstaller::CLI { struct CommandException { - CommandException(std::wstring message, std::wstring param) : m_message(message), m_param(param) {} + CommandException(std::string message, std::string param) : m_message(message), m_param(param) {} - const std::wstring& Message() const { return m_message; } - const std::wstring& Param() const { return m_param; } + const std::string& Message() const { return m_message; } + const std::string& Param() const { return m_param; } private: - std::wstring m_message; - std::wstring m_param; + std::string m_message; + std::string m_param; }; enum class ArgumentType @@ -43,16 +43,16 @@ namespace AppInstaller::CLI struct Argument { - Argument(StringLiteralPtr name, std::wstring desc) : + Argument(StringLiteralPtr name, std::string desc) : m_name(name), m_desc(std::move(desc)) {} - Argument(StringLiteralPtr name, std::wstring desc, bool required) : + Argument(StringLiteralPtr name, std::string desc, bool required) : m_name(name), m_desc(std::move(desc)), m_required(required) {} - Argument(StringLiteralPtr name, std::wstring desc, ArgumentType type) : + Argument(StringLiteralPtr name, std::string desc, ArgumentType type) : m_name(name), m_desc(std::move(desc)), m_type(type) {} - Argument(StringLiteralPtr name, std::wstring desc, ArgumentType type, bool required) : + Argument(StringLiteralPtr name, std::string desc, ArgumentType type, bool required) : m_name(name), m_desc(std::move(desc)), m_type(type), m_required(required) {} ~Argument() = default; @@ -64,14 +64,14 @@ namespace AppInstaller::CLI Argument& operator=(Argument&&) = default; StringLiteralPtrRef Name() const { return m_name; } - std::wstring Description() const { return m_desc; } + std::string Description() const { return m_desc; } bool Required() const { return m_required; } ArgumentType Type() const { return m_type; } size_t Limit() const { return m_countLimit; } private: StringLiteralPtrRef m_name; - std::wstring m_desc; + std::string m_desc; bool m_required = false; ArgumentType m_type = ArgumentType::Standard; size_t m_countLimit = 1; @@ -93,20 +93,20 @@ namespace AppInstaller::CLI virtual std::vector<std::unique_ptr<Command>> GetCommands() const { return {}; } virtual std::vector<Argument> GetArguments() const { return {}; } - virtual std::wstring ShortDescription() const { return {}; } - virtual std::vector<std::wstring> GetLongDescription() const { return {}; } + virtual std::string ShortDescription() const { return {}; } + virtual std::vector<std::string> GetLongDescription() const { return {}; } - virtual void OutputIntroHeader(std::wostream& out) const; - virtual void OutputHelp(std::wostream& out, const CommandException* exception = nullptr) const; + virtual void OutputIntroHeader(std::ostream& out) const; + virtual void OutputHelp(std::ostream& out, const CommandException* exception = nullptr) const; virtual std::unique_ptr<Command> FindInvokedCommand(Invocation& inv) const; virtual void ParseArguments(Invocation& inv) const; virtual void ValidateArguments(Invocation& inv) const; - virtual void Execute(Invocation& inv, std::wostream& out) const; + virtual void Execute(Invocation& inv, std::ostream& out) const; protected: - virtual void ExecuteInternal(Invocation& inv, std::wostream& out) const; + virtual void ExecuteInternal(Invocation& inv, std::ostream& out) const; private: StringLiteralPtrRef m_name; diff --git a/src/AppInstallerCLICore/Commands/DescribeCommand.cpp b/src/AppInstallerCLICore/Commands/DescribeCommand.cpp @@ -9,20 +9,20 @@ namespace AppInstaller::CLI std::vector<Argument> DescribeCommand::GetArguments() const { return { - Argument{ L"application", LOCME(L"The name of the application to install"), ArgumentType::Positional, true }, - Argument{ L"manifest", LOCME(L"If specified, output the full manifest file"), ArgumentType::Flag }, + Argument{ "application", LOCME("The name of the application to install"), ArgumentType::Positional, true }, + Argument{ "manifest", LOCME("If specified, output the full manifest file"), ArgumentType::Flag }, }; } - std::wstring DescribeCommand::ShortDescription() const + std::string DescribeCommand::ShortDescription() const { - return LOCME(L"Describes the given application"); + return LOCME("Describes the given application"); } - std::vector<std::wstring> DescribeCommand::GetLongDescription() const + std::vector<std::string> DescribeCommand::GetLongDescription() const { return { - LOCME(L"Describes the given application"), + LOCME("Describes the given application"), }; } } diff --git a/src/AppInstallerCLICore/Commands/DescribeCommand.h b/src/AppInstallerCLICore/Commands/DescribeCommand.h @@ -7,11 +7,11 @@ namespace AppInstaller::CLI { struct DescribeCommand final : public Command { - DescribeCommand() : Command(L"describe") {} + DescribeCommand() : Command("describe") {} virtual std::vector<Argument> GetArguments() const override; - virtual std::wstring ShortDescription() const override; - virtual std::vector<std::wstring> GetLongDescription() const override; + virtual std::string ShortDescription() const override; + virtual std::vector<std::string> GetLongDescription() const override; }; } diff --git a/src/AppInstallerCLICore/Commands/InstallCommand.cpp b/src/AppInstallerCLICore/Commands/InstallCommand.cpp @@ -9,19 +9,19 @@ namespace AppInstaller::CLI std::vector<Argument> InstallCommand::GetArguments() const { return { - Argument{ L"application", LOCME(L"The name of the application to install"), ArgumentType::Positional, true }, + Argument{ "application", LOCME("The name of the application to install"), ArgumentType::Positional, true }, }; } - std::wstring InstallCommand::ShortDescription() const + std::string InstallCommand::ShortDescription() const { - return LOCME(L"Installs the given application"); + return LOCME("Installs the given application"); } - std::vector<std::wstring> InstallCommand::GetLongDescription() const + std::vector<std::string> InstallCommand::GetLongDescription() const { return { - LOCME(L"Installs the given application"), + LOCME("Installs the given application"), }; } } diff --git a/src/AppInstallerCLICore/Commands/InstallCommand.h b/src/AppInstallerCLICore/Commands/InstallCommand.h @@ -7,11 +7,11 @@ namespace AppInstaller::CLI { struct InstallCommand final : public Command { - InstallCommand() : Command(L"install") {} + InstallCommand() : Command("install") {} virtual std::vector<Argument> GetArguments() const override; - virtual std::wstring ShortDescription() const override; - virtual std::vector<std::wstring> GetLongDescription() const override; + virtual std::string ShortDescription() const override; + virtual std::vector<std::string> GetLongDescription() const override; }; } diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp @@ -17,15 +17,15 @@ namespace AppInstaller::CLI }); } - std::vector<std::wstring> RootCommand::GetLongDescription() const + std::vector<std::string> RootCommand::GetLongDescription() const { return { - LOCME(L"AppInstaller command line utility enables installing applications from the"), - LOCME(L"command line."), + LOCME("AppInstaller command line utility enables installing applications from the"), + LOCME("command line."), }; } - void RootCommand::ExecuteInternal(Invocation&, std::wostream& out) const + void RootCommand::ExecuteInternal(Invocation&, std::ostream& out) const { OutputHelp(out); } diff --git a/src/AppInstallerCLICore/Commands/RootCommand.h b/src/AppInstallerCLICore/Commands/RootCommand.h @@ -7,13 +7,13 @@ namespace AppInstaller::CLI { struct RootCommand final : public Command { - RootCommand() : Command(L"root") {} + RootCommand() : Command("root") {} virtual std::vector<std::unique_ptr<Command>> GetCommands() const override; - virtual std::vector<std::wstring> GetLongDescription() const override; + virtual std::vector<std::string> GetLongDescription() const override; protected: - virtual void ExecuteInternal(Invocation& inv, std::wostream& out) const; + virtual void ExecuteInternal(Invocation& inv, std::ostream& out) const; }; } diff --git a/src/AppInstallerCLICore/Common.h b/src/AppInstallerCLICore/Common.h @@ -4,6 +4,6 @@ namespace AppInstaller::CLI { - using StringLiteralPtr = wchar_t const* const; - using StringLiteralPtrRef = wchar_t const*; + using StringLiteralPtr = char const* const; + using StringLiteralPtrRef = char const*; } diff --git a/src/AppInstallerCLICore/Core.cpp b/src/AppInstallerCLICore/Core.cpp @@ -8,58 +8,98 @@ using namespace winrt; using namespace Windows::Foundation; using namespace AppInstaller::CLI; -int CLICoreMain(int argc, wchar_t const** argv) try +namespace AppInstaller::CLI { - init_apartment(); - TelemetryTraceLogger::GetInstance().LogMessage(L"Launched PackageManager Client."); - RootCommand root; - Invocation invocation{ argc, argv }; + int CoreMain(int argc, wchar_t const** argv) try + { + init_apartment(); - // The root command is our fallback in the event of very bad or very little input - Command* commandToExecute = &root; - std::unique_ptr<Command> foundCommand; + // Enable logging (*all* for now, TODO: add common arguments to allow control of logging) + Logging::Log().EnableChannel(Logging::Channel::All); + Logging::Log().SetLevel(Logging::Level::Verbose); + Logging::AddDefaultFileLogger(); + Logging::EnableWilFailureTelemetry(); - try - { - foundCommand = root.FindInvokedCommand(invocation); - if (foundCommand) + // Convert incoming wide char args to UTF8 + std::vector<std::string> utf8Args; + for (int i = 1; i < argc; ++i) { - commandToExecute = foundCommand.get(); + utf8Args.emplace_back(Utility::ConvertToUTF8(argv[i])); } - commandToExecute->ParseArguments(invocation); - commandToExecute->ValidateArguments(invocation); - } - // Exceptions specific to parsing the arguments of a command - catch (const CommandException& ce) - { - commandToExecute->OutputHelp(std::wcout, &ce); - return CLICORE_ERROR_INVALID_CL_ARGUMENTS; - } - try - { - commandToExecute->Execute(invocation, std::wcout); + AICLI_LOG(CLI, Info, << "AppInstaller CLI invoked with arguments:" << [&]() { + std::stringstream strstr; + for (const auto& arg : utf8Args) + { + strstr << " '" << arg << '\''; + } + return strstr.str(); + }()); + + RootCommand root; + Invocation invocation{ std::move(utf8Args) }; + + // The root command is our fallback in the event of very bad or very little input + Command* commandToExecute = &root; + std::unique_ptr<Command> foundCommand; + + try + { + foundCommand = root.FindInvokedCommand(invocation); + if (foundCommand) + { + commandToExecute = foundCommand.get(); + } + AICLI_LOG(CLI, Info, << "Leaf command to execute: " << commandToExecute->Name()); + + commandToExecute->ParseArguments(invocation); + commandToExecute->ValidateArguments(invocation); + } + // Exceptions specific to parsing the arguments of a command + catch (const CommandException& ce) + { + commandToExecute->OutputHelp(std::cout, &ce); + AICLI_LOG(CLI, Error, << "Error encountered parsing command line: " << ce.Message()); + return CLICORE_ERROR_INVALID_CL_ARGUMENTS; + } + + try + { + commandToExecute->Execute(invocation, std::cout); + } + // Exceptions that may occur in the process of executing an arbitrary command + catch (const winrt::hresult_error& hre) + { + // TODO: Better error output + std::string message = Utility::ConvertToUTF8(hre.message()); + std::cout << "An error occured while executing the command: " << message << std::endl; + AICLI_LOG(CLI, Error, << "Error encountered executing command: " << message); + return CLICORE_ERROR_COMMAND_FAILED; + } + catch (const std::exception& e) + { + // TODO: Better error output + std::cout << "An error occured while executing the command: " << e.what() << std::endl; + AICLI_LOG(CLI, Error, << "Error encountered executing command: " << e.what()); + return CLICORE_ERROR_COMMAND_FAILED; + } + + return 0; } - // Exceptions that may occur in the process of executing an arbitrary command + // End of the line exceptions that are not ever expected. + // Telemetry cannot be reliable beyond this point, so don't let these happen. catch (const winrt::hresult_error&) { - + return CLICORE_ERROR_INTERNAL_ERROR; } catch (const std::exception&) { - + return CLICORE_ERROR_INTERNAL_ERROR; + } + catch (...) + { + return CLICORE_ERROR_INTERNAL_ERROR; } - return 0; -} -// End of the line exceptions that are not ever expected. -// Telemetry cannot be reliable beyond this point, so don't let these happen. -catch (const winrt::hresult_error&) -{ - return CLICORE_ERROR_INTERNAL_ERROR; -} -catch (const std::exception&) -{ - return CLICORE_ERROR_INTERNAL_ERROR; } diff --git a/src/AppInstallerCLICore/Invocation.h b/src/AppInstallerCLICore/Invocation.h @@ -2,6 +2,7 @@ // Licensed under the MIT License. #pragma once #include <map> +#include <vector> #include "Common.h" @@ -9,40 +10,41 @@ namespace AppInstaller::CLI { struct Invocation { - using ArgString = wchar_t const*; + using ArgString = char const*; - Invocation(int argc, ArgString* argv) : m_argc(argc), m_argv(argv) {} + Invocation(std::vector<std::string>&& args) : m_args(std::move(args)) {} struct iterator { - iterator(int arg, ArgString* argv) : m_arg(arg), m_argv(argv) {} + iterator(size_t arg, std::vector<std::string>& args) : m_arg(arg), m_args(args) {} iterator(const iterator&) = default; iterator& operator=(const iterator&) = default; - iterator operator++() { return { ++m_arg, m_argv }; } - iterator operator++(int) { return { m_arg++, m_argv }; } - iterator operator--() { return { --m_arg, m_argv }; } - iterator operator--(int) { return { m_arg--, m_argv }; } + iterator operator++() { return { ++m_arg, m_args }; } + iterator operator++(int) { return { m_arg++, m_args }; } + iterator operator--() { return { --m_arg, m_args }; } + iterator operator--(int) { return { m_arg--, m_args }; } bool operator==(const iterator& other) { return m_arg == other.m_arg; } bool operator!=(const iterator& other) { return m_arg != other.m_arg; } - ArgString operator*() const { return m_argv[m_arg]; } + const std::string& operator*() const { return m_args[m_arg]; } + const std::string* operator->() const { return &(m_args[m_arg]); } - int index() const { return m_arg; } + size_t index() const { return m_arg; } private: - int m_arg; - ArgString* m_argv; + size_t m_arg; + std::vector<std::string>& m_args; }; - iterator begin() { return { m_currentFirstArg, m_argv }; } - iterator end() { return { m_argc, m_argv }; } + iterator begin() { return { m_currentFirstArg, m_args }; } + iterator end() { return { m_args.size(), m_args }; } void consume(const iterator& i) { m_currentFirstArg = i.index() + 1; } bool Contains(StringLiteralPtrRef name) const { return (m_parsedArgs.count(name) != 0); } - const std::vector<std::wstring>* GetArgs(StringLiteralPtrRef name) const + const std::vector<std::string>* GetArgs(StringLiteralPtrRef name) const { auto itr = m_parsedArgs.find(name); return (itr == m_parsedArgs.end() ? nullptr : &(itr->second)); @@ -53,14 +55,21 @@ namespace AppInstaller::CLI return (args ? args->size() : 0); } - bool AddArg(StringLiteralPtrRef name) { return m_parsedArgs[name].empty(); } - void AddArg(StringLiteralPtrRef name, std::wstring value) { m_parsedArgs[name].emplace_back(std::move(value)); } + bool AddArg(StringLiteralPtrRef name) + { + AICLI_LOG(CLI, Verbose, << "Found flag: " << name); + return m_parsedArgs[name].empty(); + } + void AddArg(StringLiteralPtrRef name, std::string value) + { + AICLI_LOG(CLI, Verbose, << "Found argument with value: " << name << " => " << value); + m_parsedArgs[name].emplace_back(std::move(value)); + } private: - int m_argc; - ArgString* m_argv; - int m_currentFirstArg = 1; + std::vector<std::string> m_args; + size_t m_currentFirstArg = 0; - std::map<std::wstring, std::vector<std::wstring>> m_parsedArgs; + std::map<std::string, std::vector<std::string>> m_parsedArgs; }; } diff --git a/src/AppInstallerCLICore/Public/AppInstallerCLICore.h b/src/AppInstallerCLICore/Public/AppInstallerCLICore.h @@ -4,7 +4,11 @@ #define CLICORE_ERROR_FACILITY 0x8A150000 -#define CLICORE_ERROR_INVALID_CL_ARGUMENTS 0x8A150001 -#define CLICORE_ERROR_INTERNAL_ERROR 0x8A150002 +#define CLICORE_ERROR_INTERNAL_ERROR 0x8A150001 +#define CLICORE_ERROR_INVALID_CL_ARGUMENTS 0x8A150002 +#define CLICORE_ERROR_COMMAND_FAILED 0x8A150003 -int CLICoreMain(int argc, wchar_t const** argv); +namespace AppInstaller::CLI +{ + int CoreMain(int argc, wchar_t const** argv); +} diff --git a/src/AppInstallerCLICore/packages.config b/src/AppInstallerCLICore/packages.config @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="Microsoft.Windows.CppWinRT" version="2.0.191111.2" targetFramework="native" /> + <package id="Microsoft.Windows.ImplementationLibrary" version="1.0.191107.2" targetFramework="native" /> </packages> \ No newline at end of file diff --git a/src/AppInstallerCLICore/pch.h b/src/AppInstallerCLICore/pch.h @@ -3,10 +3,14 @@ #pragma once #include <windows.h> -#include "TelemetryWrapper.h" +#include "AppInstallerLogging.h" +#include "AppInstallerTelemetry.h" +#include "AppInstallerStrings.h" #include <winrt/Windows.Foundation.h> #include <winrt/Windows.Foundation.Collections.h> #include <iostream> -#include <memory>- \ No newline at end of file +#include <memory> +#include <sstream> +#include <vector> diff --git a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj @@ -108,7 +108,7 @@ <ClCompile> <Optimization>Disabled</Optimization> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;$(MSBuildThisFileDirectory)..\YamlCppLib\yaml-cpp\include</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(MSBuildThisFileDirectory)..\AppInstallerCommonCore;$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)..\YamlCppLib\yaml-cpp\include</AdditionalIncludeDirectories> </ClCompile> <Link> <SubSystem>Console</SubSystem> @@ -119,7 +119,7 @@ <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'"> <ClCompile> <PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;$(MSBuildThisFileDirectory)..\YamlCppLib\yaml-cpp\include</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(MSBuildThisFileDirectory)..\AppInstallerCommonCore;$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)..\YamlCppLib\yaml-cpp\include</AdditionalIncludeDirectories> </ClCompile> <Link> <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">winsqlite3.lib;%(AdditionalDependencies)</AdditionalDependencies> @@ -131,8 +131,8 @@ <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;$(MSBuildThisFileDirectory)..\YamlCppLib\yaml-cpp\include</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;$(MSBuildThisFileDirectory)..\YamlCppLib\yaml-cpp\include</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(MSBuildThisFileDirectory)..\AppInstallerCommonCore;$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)..\YamlCppLib\yaml-cpp\include</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(MSBuildThisFileDirectory)..\AppInstallerCommonCore;$(MSBuildThisFileDirectory)..\AppInstallerRepositoryCore;%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)..\YamlCppLib\yaml-cpp\include</AdditionalIncludeDirectories> </ClCompile> <Link> <SubSystem>Console</SubSystem> @@ -173,6 +173,9 @@ <None Include="PropertySheet.props" /> </ItemGroup> <ItemGroup> + <ProjectReference Include="..\AppInstallerCommonCore\AppInstallerCommonCore.vcxproj"> + <Project>{5890d6ed-7c3b-40f3-b436-b54f640d9e65}</Project> + </ProjectReference> <ProjectReference Include="..\AppInstallerRepositoryCore\AppInstallerRepositoryCore.vcxproj"> <Project>{5eb88068-5fb9-4e69-89b2-72dbc5e068f9}</Project> </ProjectReference> diff --git a/src/AppInstallerCLITests/main.cpp b/src/AppInstallerCLITests/main.cpp @@ -6,6 +6,9 @@ #include <string> #include <vector> +#include <Public/AppInstallerLogging.h> +#include <Public/AppInstallerTelemetry.h> + #include "TestCommon.h" using namespace winrt; @@ -29,5 +32,11 @@ int main(int argc, char** argv) } } + // Enable all logging, to force log string building to run. + // By not creating a log target, it will all be thrown away. + AppInstaller::Logging::Log().EnableChannel(AppInstaller::Logging::Channel::All); + AppInstaller::Logging::Log().SetLevel(AppInstaller::Logging::Level::Verbose); + AppInstaller::Logging::EnableWilFailureTelemetry(); + return Catch::Session().run(static_cast<int>(args.size()), args.data()); } diff --git a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj @@ -0,0 +1,207 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.props')" /> + <PropertyGroup Label="Globals"> + <CppWinRTOptimized>true</CppWinRTOptimized> + <CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge> + <MinimalCoreWin>true</MinimalCoreWin> + <VCProjectVersion>15.0</VCProjectVersion> + <ProjectGuid>{5890d6ed-7c3b-40f3-b436-b54f640d9e65}</ProjectGuid> + <Keyword>Win32Proj</Keyword> + <RootNamespace>AppInstallerLoggingCore</RootNamespace> + <WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion> + <WindowsTargetPlatformMinVersion>10.0.16299.0</WindowsTargetPlatformMinVersion> + <WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport> + <WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|ARM"> + <Configuration>Debug</Configuration> + <Platform>ARM</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|ARM64"> + <Configuration>Debug</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM"> + <Configuration>Release</Configuration> + <Platform>ARM</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|ARM64"> + <Configuration>Release</Configuration> + <Platform>ARM64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <PlatformToolset>v140</PlatformToolset> + <PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset> + <PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> + <UseDebugLibraries>true</UseDebugLibraries> + <LinkIncremental>true</LinkIncremental> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> + <UseDebugLibraries>false</UseDebugLibraries> + <WholeProgramOptimization>true</WholeProgramOptimization> + <LinkIncremental>false</LinkIncremental> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Label="Shared" /> + <ImportGroup Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Label="PropertySheets"> + <Import Project="PropertySheet.props" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(SolutionDir)x86\$(Configuration)\$(ProjectName)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(SolutionDir)x86\$(Configuration)\$(ProjectName)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</OutDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</OutDir> + </PropertyGroup> + <ItemDefinitionGroup> + <ClCompile> + <PrecompiledHeader>Use</PrecompiledHeader> + <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> + <PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile> + <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <WarningLevel>Level4</WarningLevel> + <AdditionalOptions>%(AdditionalOptions) /permissive- /bigobj</AdditionalOptions> + </ClCompile> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions);CLICOREDLLBUILD</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(ProjectDir);$(ProjectDir)Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(ProjectDir);$(ProjectDir)Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir);$(ProjectDir)Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <GenerateWindowsMetadata>false</GenerateWindowsMetadata> + <SubSystem Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Windows</SubSystem> + <SubSystem Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Windows</SubSystem> + <SubSystem Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Windows</SubSystem> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'"> + <ClCompile> + <PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions);CLICOREDLLBUILD</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir);$(ProjectDir)Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <SubSystem Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Windows</SubSystem> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'"> + <ClCompile> + <Optimization>MaxSpeed</Optimization> + <FunctionLevelLinking>true</FunctionLevelLinking> + <IntrinsicFunctions>true</IntrinsicFunctions> + <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions);CLICOREDLLBUILD</PreprocessorDefinitions> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(ProjectDir);$(ProjectDir)Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(ProjectDir);$(ProjectDir)Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir);$(ProjectDir)Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir);$(ProjectDir)Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + </ClCompile> + <Link> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <OptimizeReferences>true</OptimizeReferences> + <GenerateWindowsMetadata>false</GenerateWindowsMetadata> + <SubSystem Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Windows</SubSystem> + <SubSystem Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Windows</SubSystem> + <SubSystem Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Windows</SubSystem> + <SubSystem Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Windows</SubSystem> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClInclude Include="DateTime.h" /> + <ClInclude Include="FileLogger.h" /> + <ClInclude Include="pch.h" /> + <ClInclude Include="Public\AppInstallerRuntime.h" /> + <ClInclude Include="Public\AppInstallerStrings.h" /> + <ClInclude Include="Public\AppInstallerTelemetry.h" /> + <ClInclude Include="Public\AppInstallerLogging.h" /> + <ClInclude Include="Telemetry\MicrosoftTelemetry.h" /> + <ClInclude Include="Telemetry\TraceLogging.h" /> + <ClInclude Include="Telemetry\WinEventLogLevels.h" /> + </ItemGroup> + <ItemGroup> + <ClCompile Include="AppInstallerLogging.cpp" /> + <ClCompile Include="AppInstallerStrings.cpp" /> + <ClCompile Include="DateTime.cpp" /> + <ClCompile Include="FileLogger.cpp" /> + <ClCompile Include="Runtime.cpp" /> + <ClCompile Include="pch.cpp"> + <PrecompiledHeader>Create</PrecompiledHeader> + </ClCompile> + <ClCompile Include="AppInstallerTelemetry.cpp" /> + <ClCompile Include="Telemetry\TraceLogging.cpp" /> + </ItemGroup> + <ItemGroup> + <None Include="packages.config" /> + <None Include="PropertySheet.props" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + <Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.targets')" /> + <Import Project="$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.191107.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.191107.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" /> + </ImportGroup> + <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> + <PropertyGroup> + <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> + </PropertyGroup> + <Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.props'))" /> + <Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.191111.2\build\native\Microsoft.Windows.CppWinRT.targets'))" /> + <Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.191107.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Microsoft.Windows.ImplementationLibrary.1.0.191107.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" /> + </Target> +</Project>+ \ No newline at end of file diff --git a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> + <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> + </Filter> + <Filter Include="Telemetry - Do Not Modify"> + <UniqueIdentifier>{552a58eb-8d07-41b2-87b5-3e71b9fb3cfd}</UniqueIdentifier> + </Filter> + <Filter Include="Public"> + <UniqueIdentifier>{5cdf3fa3-e657-4d84-81bb-f740aa476143}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClInclude Include="pch.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="Telemetry\MicrosoftTelemetry.h"> + <Filter>Telemetry - Do Not Modify</Filter> + </ClInclude> + <ClInclude Include="Telemetry\TraceLogging.h"> + <Filter>Telemetry - Do Not Modify</Filter> + </ClInclude> + <ClInclude Include="Telemetry\WinEventLogLevels.h"> + <Filter>Telemetry - Do Not Modify</Filter> + </ClInclude> + <ClInclude Include="Public\AppInstallerTelemetry.h"> + <Filter>Public</Filter> + </ClInclude> + <ClInclude Include="Public\AppInstallerLogging.h"> + <Filter>Public</Filter> + </ClInclude> + <ClInclude Include="Public\AppInstallerStrings.h"> + <Filter>Public</Filter> + </ClInclude> + <ClInclude Include="FileLogger.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="DateTime.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="Public\AppInstallerRuntime.h"> + <Filter>Public</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <ClCompile Include="pch.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Telemetry\TraceLogging.cpp"> + <Filter>Telemetry - Do Not Modify</Filter> + </ClCompile> + <ClCompile Include="AppInstallerTelemetry.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="AppInstallerLogging.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="AppInstallerStrings.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="FileLogger.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="DateTime.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Runtime.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <None Include="PropertySheet.props" /> + <None Include="packages.config" /> + </ItemGroup> +</Project>+ \ No newline at end of file diff --git a/src/AppInstallerCommonCore/AppInstallerLogging.cpp b/src/AppInstallerCommonCore/AppInstallerLogging.cpp @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "Public/AppInstallerLogging.h" + +#include "Public/AppInstallerTelemetry.h" +#include "FileLogger.h" + +namespace AppInstaller::Logging +{ + namespace + { + template <typename E> + std::underlying_type_t<E> AsNum(E e) + { + return static_cast<std::underlying_type_t<E>>(e); + } + + uint64_t ConvertChannelToBitmask(Channel channel) + { + if (channel == Channel::All) + { + return std::numeric_limits<uint64_t>::max(); + } + else + { + return (1ull << AsNum(channel)); + } + } + } + + char const* const GetChannelName(Channel channel) + { + switch(channel) + { + case Channel::Fail: return "FAIL"; + case Channel::CLI: return "CLI"; + case Channel::SQL: return "SQL"; + case Channel::Repo: return "REPO"; + case Channel::YAML: return "YAML"; + default: return "NONE"; + } + } + + size_t GetMaxChannelNameLength() { return 4; } + + DiagnosticLogger& DiagnosticLogger::GetInstance() + { + static DiagnosticLogger instance; + return instance; + } + + void DiagnosticLogger::AddLogger(std::unique_ptr<ILogger>&& logger) + { + m_loggers.emplace_back(std::move(logger)); + } + + std::unique_ptr<ILogger> DiagnosticLogger::RemoveLogger(const std::string& name) + { + std::unique_ptr<ILogger> result; + + for (auto i = m_loggers.begin(); i != m_loggers.end(); ++i) + { + if ((*i)->GetName() == name) + { + result = std::move(*i); + m_loggers.erase(i); + break; + } + } + + return result; + } + + void DiagnosticLogger::EnableChannel(Channel channel) + { + m_enabledChannels |= ConvertChannelToBitmask(channel); + } + + void DiagnosticLogger::DisableChannel(Channel channel) + { + m_enabledChannels &= ~ConvertChannelToBitmask(channel); + } + + void DiagnosticLogger::SetLevel(Level level) + { + m_enabledLevel = level; + } + + bool DiagnosticLogger::IsEnabled(Channel channel, Level level) const + { + return ((m_enabledChannels & ConvertChannelToBitmask(channel)) != 0 && + (AsNum(level) >= AsNum(m_enabledLevel))); + } + + void DiagnosticLogger::Write(Channel channel, Level level, std::string_view message) + { + THROW_HR_IF_MSG(E_INVALIDARG, channel == Channel::All, "Cannot write to all channels"); + + if (IsEnabled(channel, level)) + { + for (auto& logger : m_loggers) + { + logger->Write(channel, level, message); + } + } + } + + void AddDefaultFileLogger() + { + Log().AddLogger(std::make_unique<FileLogger>()); + } +} diff --git a/src/AppInstallerCommonCore/AppInstallerStrings.cpp b/src/AppInstallerCommonCore/AppInstallerStrings.cpp @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "Public/AppInstallerStrings.h" + + +namespace AppInstaller::Utility +{ + std::string ConvertToUTF8(std::wstring_view input) + { + int utf8ByteCount = WideCharToMultiByte(CP_UTF8, 0, input.data(), wil::safe_cast<int>(input.length()), nullptr, 0, nullptr, nullptr); + THROW_LAST_ERROR_IF(utf8ByteCount == 0); + + // Since the string view should not contain the null char, the result won't either. + // This allows us to use the resulting size value directly in the string constructor. + std::string result(wil::safe_cast<size_t>(utf8ByteCount), '\0'); + + int utf8BytesWritten = WideCharToMultiByte(CP_UTF8, 0, input.data(), wil::safe_cast<int>(input.length()), &result[0], wil::safe_cast<int>(result.size()), nullptr, nullptr); + FAIL_FAST_HR_IF(E_UNEXPECTED, utf8ByteCount != utf8BytesWritten); + + return result; + } + + std::wstring ConvertToUTF16(std::string_view input) + { + int utf16CharCount = MultiByteToWideChar(CP_UTF8, 0, input.data(), wil::safe_cast<int>(input.length()), nullptr, 0); + THROW_LAST_ERROR_IF(utf16CharCount == 0); + + // Since the string view should not contain the null char, the result won't either. + // This allows us to use the resulting size value directly in the string constructor. + std::wstring result(wil::safe_cast<size_t>(utf16CharCount), L'\0'); + + int utf16CharsWritten = MultiByteToWideChar(CP_UTF8, 0, input.data(), wil::safe_cast<int>(input.length()), &result[0], wil::safe_cast<int>(result.size())); + FAIL_FAST_HR_IF(E_UNEXPECTED, utf16CharCount != utf16CharsWritten); + + return result; + } +} diff --git a/src/AppInstallerCommonCore/AppInstallerTelemetry.cpp b/src/AppInstallerCommonCore/AppInstallerTelemetry.cpp @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "Public/AppInstallerTelemetry.h" + +#include "Public/AppInstallerLogging.h" +#include "Public/AppInstallerStrings.h" + +namespace AppInstaller::Logging +{ + namespace + { + void __stdcall wilResultLoggingCallback(const wil::FailureInfo& info) noexcept + { + Telemetry().LogFailure(info); + } + } + + TelemetryTraceLogger::TelemetryTraceLogger() + { + RegisterTraceLogging(); + } + + TelemetryTraceLogger::~TelemetryTraceLogger() + { + UnRegisterTraceLogging(); + } + + TelemetryTraceLogger& TelemetryTraceLogger::GetInstance() + { + static TelemetryTraceLogger instance; + return instance; + } + + void TelemetryTraceLogger::LogFailure(const wil::FailureInfo& failure) noexcept + { + if (g_IsTelemetryProviderEnabled) + { + TraceLoggingWrite(g_hTelemetryProvider, + "FailureInfo", + TraceLoggingHResult(failure.hr, "hr"), + TraceLoggingWideString(failure.pszMessage, "message"), + TraceLoggingString(failure.pszModule, "module"), + TraceLoggingUInt32(failure.threadId, "threadId"), + TraceLoggingUInt32(static_cast<uint32_t>(failure.type), "type"), + TraceLoggingString(failure.pszFile, "file"), + TraceLoggingUInt32(failure.uLineNumber, "line"), + TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance), + TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES)); + } + + // Also send failure to the log + AICLI_LOG(Fail, Error, << [&]() { + wchar_t message[2048]; + GetFailureLogString(message, ARRAYSIZE(message), failure); + return Utility::ConvertToUTF8(message); + }()); + } + + void EnableWilFailureTelemetry() + { + wil::SetResultLoggingCallback(wilResultLoggingCallback); + } +}+ \ No newline at end of file diff --git a/src/AppInstallerCommonCore/DateTime.cpp b/src/AppInstallerCommonCore/DateTime.cpp @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "DateTime.h" + +namespace AppInstaller::Utility +{ + // If moved to C++20, this can be replaced with standard library implementations. + void OutputTimepoint(std::ostream& stream, const std::chrono::system_clock::time_point& time) + { + using namespace std::chrono; + + tm localTime{}; + auto tt = system_clock::to_time_t(time); + _localtime64_s(&localTime, &tt); + + // Don't bother with fill chars for dates, as most of the time this won't be an issue. + stream << (1900 + localTime.tm_year) << '-' << (1 + localTime.tm_mon) << '-' << localTime.tm_mday << ' ' + << std::setw(2) << std::setfill('0') << localTime.tm_hour << ':' + << std::setw(2) << std::setfill('0') << localTime.tm_min << ':' + << std::setw(2) << std::setfill('0') << localTime.tm_sec << '.'; + + // Get partial seconds + auto sinceEpoch = time.time_since_epoch(); + auto leftoverMillis = duration_cast<milliseconds>(sinceEpoch) - duration_cast<seconds>(sinceEpoch); + + stream << std::setw(3) << std::setfill('0') << leftoverMillis.count(); + } +} diff --git a/src/AppInstallerCommonCore/DateTime.h b/src/AppInstallerCommonCore/DateTime.h @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once + +#include <chrono> +#include <ostream> + +namespace AppInstaller::Utility +{ + // Writes the given time to the given stream. + // Assumes that system_clock uses Linux epoch (as required by C++20 standard). + // Time is also assumed to be after the epoch. + void OutputTimepoint(std::ostream& stream, const std::chrono::system_clock::time_point& time); +} diff --git a/src/AppInstallerCommonCore/FileLogger.cpp b/src/AppInstallerCommonCore/FileLogger.cpp @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "FileLogger.h" + +#include "Public/AppInstallerRuntime.h" +#include "DateTime.h" + +#define AICLI_FILELOGGER_DEFAULT_FILE "AICLI.log" + +namespace AppInstaller::Logging +{ + + FileLogger::FileLogger(const std::filesystem::path& filePath) + { + if (filePath.empty()) + { + m_name = "file"; + m_filePath = Runtime::GetPathToTemp(); + m_filePath /= AICLI_FILELOGGER_DEFAULT_FILE; + } + else + { + m_name = GetNameForPath(filePath); + m_filePath = filePath; + } + + m_stream.open(m_filePath); + } + + FileLogger::~FileLogger() + { + m_stream.flush(); + } + + std::string FileLogger::GetNameForPath(const std::filesystem::path& filePath) + { + using namespace std::string_literals; + return "file :: "s + filePath.u8string(); + } + + std::string FileLogger::GetName() const + { + return m_name; + } + + void FileLogger::Write(Channel channel, Level, std::string_view message) noexcept try + { + Utility::OutputTimepoint(m_stream, std::chrono::system_clock::now()); + m_stream << " [" << std::setw(GetMaxChannelNameLength()) << std::left << std::setfill(' ') << GetChannelName(channel) << "] " << message << std::endl; + } + catch (...) + { + // Just eat any exceptions here; better than losing logs + } +} diff --git a/src/AppInstallerCommonCore/FileLogger.h b/src/AppInstallerCommonCore/FileLogger.h @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once +#include "Public/AppInstallerLogging.h" + +#include <filesystem> +#include <fstream> +#include <string> + +namespace AppInstaller::Logging +{ + // Logs to a file. + struct FileLogger : public ILogger + { + FileLogger(const std::filesystem::path& filePath = {}); + + ~FileLogger(); + + FileLogger(const FileLogger&) = delete; + FileLogger& operator=(const FileLogger&) = delete; + + FileLogger(FileLogger&&) = default; + FileLogger& operator=(FileLogger&&) = default; + + static std::string GetNameForPath(const std::filesystem::path& filePath); + + // ILogger + virtual std::string GetName() const override; + + virtual void Write(Channel channel, Level level, std::string_view message) noexcept override; + + private: + std::string m_name; + std::filesystem::path m_filePath; + std::ofstream m_stream; + }; +} diff --git a/src/AppInstallerCommonCore/PropertySheet.props b/src/AppInstallerCommonCore/PropertySheet.props @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ImportGroup Label="PropertySheets" /> + <PropertyGroup Label="UserMacros" /> + <!-- + To customize common C++/WinRT project properties: + * right-click the project node + * expand the Common Properties item + * select the C++/WinRT property page + + For more advanced scenarios, and complete documentation, please see: + https://github.com/Microsoft/xlang/tree/master/src/package/cppwinrt/nuget + --> + <PropertyGroup /> + <ItemDefinitionGroup /> +</Project>+ \ No newline at end of file diff --git a/src/AppInstallerCommonCore/Public/AppInstallerLogging.h b/src/AppInstallerCommonCore/Public/AppInstallerLogging.h @@ -0,0 +1,120 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once + +#include <memory> +#include <sstream> +#include <string> +#include <string_view> +#include <vector> + +#define AICLI_LOG(_channel_,_level_,_outstream_) \ + do { \ + auto _aicli_log_channel = AppInstaller::Logging::Channel:: ## _channel_; \ + auto _aicli_log_level = AppInstaller::Logging::Level:: ## _level_; \ + auto& _aicli_log_log = AppInstaller::Logging::Log(); \ + if (_aicli_log_log.IsEnabled(_aicli_log_channel, _aicli_log_level)) \ + { \ + std::stringstream _aicli_log_strstr; \ + _aicli_log_strstr _outstream_; \ + _aicli_log_log.Write(_aicli_log_channel, _aicli_log_level, _aicli_log_strstr.str()); \ + } \ + } while (0, 0) + +namespace AppInstaller::Logging +{ + // The channel that the log is from. + // Channels enable large groups of logs to be enabled or disabled together. + enum class Channel : uint32_t + { + Fail, + CLI, + SQL, + Repo, + YAML, + All, + }; + + // Gets the channel's name as a string. + char const* const GetChannelName(Channel channel); + + // Gets the maximum channel name length in characters. + size_t GetMaxChannelNameLength(); + + // The level of the log. + enum class Level + { + Verbose, + Info, + Error, + Crit, + }; + + // The interface that a log target must implement. + struct ILogger + { + virtual ~ILogger() = default; + + // Gets the name of the logger for internal use. + virtual std::string GetName() const = 0; + + // Informs the logger of the given log. + virtual void Write(Channel channel, Level level, std::string_view message) noexcept = 0; + }; + + // This type contains the set of loggers that diagnostic logging will be sent to. + // Each binary that leverages it must configure any loggers and filters to their + // desired level, as nothing is enabled by default. + struct DiagnosticLogger + { + ~DiagnosticLogger() = default; + + DiagnosticLogger(const DiagnosticLogger&) = delete; + DiagnosticLogger& operator=(const DiagnosticLogger&) = delete; + + DiagnosticLogger(DiagnosticLogger&&) = delete; + DiagnosticLogger& operator=(DiagnosticLogger&&) = delete; + + // Gets the singleton instance of this type. + static DiagnosticLogger& GetInstance(); + + // Adds a logger to the active set. + void AddLogger(std::unique_ptr<ILogger>&& logger); + + // Removes a logger from the active set, returning it. + std::unique_ptr<ILogger> RemoveLogger(const std::string& name); + + // Enables the given channel. + void EnableChannel(Channel channel); + + // Disables the given channel. + void DisableChannel(Channel channel); + + // Sets the enabled level. + // All levels higher than this level will be enabled. + // For example; SetLevel(Verbose) will enable all logs. + void SetLevel(Level level); + + // Checks whether a given channel and level are enabled. + bool IsEnabled(Channel channel, Level level) const; + + // Writes a log line, if the given channel and level are enabled. + void Write(Channel channel, Level level, std::string_view message); + + private: + DiagnosticLogger() = default; + + std::vector<std::unique_ptr<ILogger>> m_loggers; + uint64_t m_enabledChannels = 0; + Level m_enabledLevel = Level::Info; + }; + + // Helper to make the call sites look clean. + inline DiagnosticLogger& Log() + { + return DiagnosticLogger::GetInstance(); + } + + // Adds the default file logger to the DiagnosticLogger. + void AddDefaultFileLogger(); +} diff --git a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once + +#include <filesystem> + +namespace AppInstaller::Runtime +{ + // Determines whether the process is running in a packaged context or not. + bool IsRunningInPackagedContext(); + + // Gets the path to the temp location. + std::filesystem::path GetPathToTemp(); +} diff --git a/src/AppInstallerCommonCore/Public/AppInstallerStrings.h b/src/AppInstallerCommonCore/Public/AppInstallerStrings.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once + +#include <string> +#include <string_view> + +namespace AppInstaller::Utility +{ + // Converts the given UTF16 string to UTF8 + std::string ConvertToUTF8(std::wstring_view input); + + // Converts the given UTF8 string to UTF16 + std::wstring ConvertToUTF16(std::string_view input); +} diff --git a/src/AppInstallerCommonCore/Public/AppInstallerTelemetry.h b/src/AppInstallerCommonCore/Public/AppInstallerTelemetry.h @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once + +#include <wil/result_macros.h> + +#include <string_view> + +namespace AppInstaller::Logging +{ + // This type contains the registration lifetime of the telemetry trace logging provider. + // Due to the nature of trace logging, specific methods should be added per desired trace. + // As there should not be a significantly large number of individual telemetry events, + // this should not become a burden. + struct TelemetryTraceLogger + { + ~TelemetryTraceLogger(); + + TelemetryTraceLogger(const TelemetryTraceLogger&) = delete; + TelemetryTraceLogger& operator=(const TelemetryTraceLogger&) = delete; + + TelemetryTraceLogger(TelemetryTraceLogger&&) = delete; + TelemetryTraceLogger& operator=(TelemetryTraceLogger&&) = delete; + + // Gets the singleton instance of this type. + static TelemetryTraceLogger& GetInstance(); + + // Logs the failure info. + void LogFailure(const wil::FailureInfo& failure) noexcept; + + private: + TelemetryTraceLogger(); + }; + + // Helper to make the call sites look clean. + inline TelemetryTraceLogger& Telemetry() + { + return TelemetryTraceLogger::GetInstance(); + } + + // Turns on wil failure telemetry and logging. + void EnableWilFailureTelemetry(); +} diff --git a/src/AppInstallerCommonCore/Runtime.cpp b/src/AppInstallerCommonCore/Runtime.cpp @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" +#include "Public/AppInstallerRuntime.h" + +#include <winrt/Windows.Storage.h> + +namespace AppInstaller::Runtime +{ + namespace + { + bool DoesCurrentProcessHaveIdentity() + { + UINT32 length = 0; + LONG result = GetPackageFamilyName(GetCurrentProcess(), &length, nullptr); + return (result != APPMODEL_ERROR_NO_PACKAGE); + } + } + + bool IsRunningInPackagedContext() + { + static bool result = DoesCurrentProcessHaveIdentity(); + return result; + } + + std::filesystem::path GetPathToTemp() + { + if (IsRunningInPackagedContext()) + { + return { winrt::Windows::Storage::ApplicationData::Current().TemporaryFolder().Path().c_str() }; + } + else + { + wchar_t tempPath[MAX_PATH + 1]; + DWORD tempChars = GetTempPathW(ARRAYSIZE(tempPath), tempPath); + return { std::wstring_view{ tempPath, static_cast<size_t>(tempChars) } }; + } + } +} diff --git a/src/Telemetry/MicrosoftTelemetry.h b/src/AppInstallerCommonCore/Telemetry/MicrosoftTelemetry.h diff --git a/src/Telemetry/TraceLogging.cpp b/src/AppInstallerCommonCore/Telemetry/TraceLogging.cpp diff --git a/src/Telemetry/TraceLogging.h b/src/AppInstallerCommonCore/Telemetry/TraceLogging.h diff --git a/src/Telemetry/WinEventLogLevels.h b/src/AppInstallerCommonCore/Telemetry/WinEventLogLevels.h diff --git a/src/AppInstallerCommonCore/packages.config b/src/AppInstallerCommonCore/packages.config @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="Microsoft.Windows.CppWinRT" version="2.0.191111.2" targetFramework="native" /> + <package id="Microsoft.Windows.ImplementationLibrary" version="1.0.191107.2" targetFramework="native" /> +</packages>+ \ No newline at end of file diff --git a/src/AppInstallerCommonCore/pch.cpp b/src/AppInstallerCommonCore/pch.cpp @@ -0,0 +1,3 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#include "pch.h" diff --git a/src/AppInstallerCommonCore/pch.h b/src/AppInstallerCommonCore/pch.h @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +#pragma once + +#define NOMINMAX +#include <Windows.h> +#include <appmodel.h> + +#include "TraceLogging.h" + +#include <wil/result_macros.h> +#include <wil/safecast.h> + +#include <chrono> +#include <fstream> +#include <iomanip> +#include <limits> +#include <memory> +#include <ostream> +#include <string> +#include <string_view> +#include <type_traits> +#include <vector> diff --git a/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj b/src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj @@ -68,9 +68,7 @@ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> </ImportGroup> - <ImportGroup Label="Shared"> - <Import Project="..\Telemetry\Telemetry.vcxitems" Label="Shared" /> - </ImportGroup> + <ImportGroup Label="Shared" /> <ImportGroup Label="PropertySheets"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup> @@ -124,9 +122,9 @@ <ClCompile> <Optimization>Disabled</Optimization> <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions);CLICOREDLLBUILD</PreprocessorDefinitions> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(ProjectDir);..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(ProjectDir);..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir);..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;$(ProjectDir)..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;$(ProjectDir)..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;$(ProjectDir)..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ClCompile> <Link> <GenerateWindowsMetadata>false</GenerateWindowsMetadata> @@ -138,7 +136,7 @@ <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'"> <ClCompile> <PreprocessorDefinitions>WIN32;%(PreprocessorDefinitions);CLICOREDLLBUILD</PreprocessorDefinitions> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir);..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;$(ProjectDir)..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ClCompile> <Link> <SubSystem Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Windows</SubSystem> @@ -150,10 +148,10 @@ <FunctionLevelLinking>true</FunctionLevelLinking> <IntrinsicFunctions>true</IntrinsicFunctions> <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions);CLICOREDLLBUILD</PreprocessorDefinitions> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(ProjectDir);..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(ProjectDir);..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir);..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir);..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;$(ProjectDir)..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;$(ProjectDir)..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;$(ProjectDir)..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir);$(ProjectDir)..\AppInstallerCommonCore\Public;$(ProjectDir)..\YamlCppLib\yaml-cpp\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ClCompile> <Link> <EnableCOMDATFolding>true</EnableCOMDATFolding> diff --git a/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndex.cpp b/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndex.cpp @@ -7,15 +7,34 @@ namespace AppInstaller::Repository::Microsoft { + namespace + { + char const* const GetOpenDispositionString(SQLiteIndex::OpenDisposition disposition) + { + switch (disposition) + { + case AppInstaller::Repository::Microsoft::SQLiteIndex::OpenDisposition::Read: + return "Read"; + case AppInstaller::Repository::Microsoft::SQLiteIndex::OpenDisposition::ReadWrite: + return "ReadWrite"; + case AppInstaller::Repository::Microsoft::SQLiteIndex::OpenDisposition::Immutable: + return "ImmutableRead"; + default: + return "Unknown"; + } + } + } + SQLiteIndex SQLiteIndex::CreateNew(const std::string& filePath, Schema::Version version) { + AICLI_LOG(Repo, Info, << "Creating new SQLite Index [" << version << "] at '" << filePath << "'"); SQLiteIndex result{ filePath, version }; - SQLite::Savepoint savepoint = SQLite::Savepoint::Create(result._dbconn, "sqliteindex_createnew"); + SQLite::Savepoint savepoint = SQLite::Savepoint::Create(result.m_dbconn, "sqliteindex_createnew"); - Schema::MetadataTable::Create(result._dbconn); + Schema::MetadataTable::Create(result.m_dbconn); // Use calculated version, as incoming version could be 'latest' - result._version.SetSchemaVersion(result._dbconn); + result.m_version.SetSchemaVersion(result.m_dbconn); savepoint.Commit(); @@ -24,6 +43,7 @@ namespace AppInstaller::Repository::Microsoft SQLiteIndex SQLiteIndex::Open(const std::string& filePath, OpenDisposition disposition) { + AICLI_LOG(Repo, Info, << "Opening SQLite Index for " << GetOpenDispositionString(disposition) << " at '" << filePath << "'"); switch (disposition) { case AppInstaller::Repository::Microsoft::SQLiteIndex::OpenDisposition::Read: @@ -83,16 +103,17 @@ namespace AppInstaller::Repository::Microsoft } SQLiteIndex::SQLiteIndex(const std::string& target, SQLite::Connection::OpenDisposition disposition, SQLite::Connection::OpenFlags flags) : - _dbconn(SQLite::Connection::Create(target, disposition, flags)) + m_dbconn(SQLite::Connection::Create(target, disposition, flags)) { - _version = Schema::Version::GetSchemaVersion(_dbconn); - _interface = _version.CreateISQLiteIndex(); + m_version = Schema::Version::GetSchemaVersion(m_dbconn); + AICLI_LOG(Repo, Info, << "Opened SQLite Index with version: " << m_version); + m_interface = m_version.CreateISQLiteIndex(); } SQLiteIndex::SQLiteIndex(const std::string& target, Schema::Version version) : - _dbconn(SQLite::Connection::Create(target, SQLite::Connection::OpenDisposition::Create)) + m_dbconn(SQLite::Connection::Create(target, SQLite::Connection::OpenDisposition::Create)) { - _interface = version.CreateISQLiteIndex(); - _version = _interface->GetVersion(); + m_interface = version.CreateISQLiteIndex(); + m_version = m_interface->GetVersion(); } } diff --git a/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndex.h b/src/AppInstallerRepositoryCore/Microsoft/SQLiteIndex.h @@ -37,7 +37,7 @@ namespace AppInstaller::Repository::Microsoft static SQLiteIndex Open(const std::string& filePath, OpenDisposition disposition); // Gets the schema version of the index. - Schema::Version GetVersion() const { return _version; } + Schema::Version GetVersion() const { return m_version; } private: // Constructor used to open an existing index. @@ -46,8 +46,8 @@ namespace AppInstaller::Repository::Microsoft // Constructor used to create a new index. SQLiteIndex(const std::string& target, Schema::Version version); - SQLite::Connection _dbconn; - Schema::Version _version; - std::unique_ptr<Schema::ISQLiteIndex> _interface; + SQLite::Connection m_dbconn; + Schema::Version m_version; + std::unique_ptr<Schema::ISQLiteIndex> m_interface; }; } diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/Version.cpp b/src/AppInstallerRepositoryCore/Microsoft/Schema/Version.cpp @@ -39,4 +39,9 @@ namespace AppInstaller::Repository::Microsoft::Schema // We do not have the capacity to operate on this schema version THROW_HR(E_NOT_SET); } + + std::ostream& operator<<(std::ostream& out, const Version& version) + { + return (out << version.MajorVersion << '.' << version.MinorVersion); + } } diff --git a/src/AppInstallerRepositoryCore/Microsoft/Schema/Version.h b/src/AppInstallerRepositoryCore/Microsoft/Schema/Version.h @@ -48,4 +48,7 @@ namespace AppInstaller::Repository::Microsoft::Schema // Creates the interface object for this version. std::unique_ptr<ISQLiteIndex> CreateISQLiteIndex(); }; + + // Output the version + std::ostream& operator<<(std::ostream& out, const Version& version); } diff --git a/src/AppInstallerRepositoryCore/SQLiteWrapper.cpp b/src/AppInstallerRepositoryCore/SQLiteWrapper.cpp @@ -5,16 +5,21 @@ #include <wil/result_macros.h> -#define THROW_SQLITE(_error_) throw SQLiteException(_error_) +// TODO: Invoke the wil error handling callback to log the error +#define THROW_SQLITE(_error_) \ + do { \ + auto _throw_sqlite_exc = SQLiteException(_error_); \ + throw _throw_sqlite_exc; \ + } while (0,0) #define THROW_IF_SQLITE_FAILED(_statement_) \ do { \ - int _sqliteReturnValue = _statement_; \ - if (_sqliteReturnValue != SQLITE_OK) \ + int _tisf_sqliteReturnValue = _statement_; \ + if (_tisf_sqliteReturnValue != SQLITE_OK) \ { \ - THROW_SQLITE(_sqliteReturnValue); \ + THROW_SQLITE(_tisf_sqliteReturnValue); \ } \ - } while (0,0); + } while (0,0) namespace AppInstaller::Repository::SQLite { @@ -25,6 +30,12 @@ namespace AppInstaller::Repository::SQLite const char* name() const noexcept override { return "sqlite"; } std::string message(int error) const override { return sqlite3_errstr(error); } }; + + size_t GetNextStatementId() + { + static std::atomic_size_t statementId(0); + return ++statementId; + } } namespace details @@ -58,28 +69,31 @@ namespace AppInstaller::Repository::SQLite Connection::Connection(const std::string& target, OpenDisposition disposition, OpenFlags flags) { + AICLI_LOG(SQL, Info, << "Opening SQLite connection: '" << target << "' [" << std::hex << static_cast<int>(disposition) << ", " << std::hex << static_cast<int>(flags) << "]"); int resultingFlags = static_cast<int>(disposition) | static_cast<int>(flags); - THROW_IF_SQLITE_FAILED(sqlite3_open_v2(target.c_str(), &_dbconn, resultingFlags, nullptr)); + THROW_IF_SQLITE_FAILED(sqlite3_open_v2(target.c_str(), &m_dbconn, resultingFlags, nullptr)); } Connection Connection::Create(const std::string& target, OpenDisposition disposition, OpenFlags flags) { Connection result{ target, disposition, flags }; - THROW_IF_SQLITE_FAILED(sqlite3_extended_result_codes(result._dbconn, 1)); + THROW_IF_SQLITE_FAILED(sqlite3_extended_result_codes(result.m_dbconn, 1)); return result; } Connection::~Connection() { - sqlite3_close_v2(_dbconn); + sqlite3_close_v2(m_dbconn); } Statement::Statement(Connection& connection, const std::string& sql, bool persistent) { + m_id = GetNextStatementId(); + AICLI_LOG(SQL, Verbose, << "Preparing statement #" << m_id << ": " << sql); // SQL string size should include the null terminator (https://www.sqlite.org/c3ref/prepare.html) - THROW_IF_SQLITE_FAILED(sqlite3_prepare_v3(connection, sql.c_str(), static_cast<int>(sql.size() + 1), (persistent ? SQLITE_PREPARE_PERSISTENT : 0), &_stmt, nullptr)); + THROW_IF_SQLITE_FAILED(sqlite3_prepare_v3(connection, sql.c_str(), static_cast<int>(sql.size() + 1), (persistent ? SQLITE_PREPARE_PERSISTENT : 0), &m_stmt, nullptr)); } Statement Statement::Create(Connection& connection, const std::string& sql, bool persistent) @@ -89,26 +103,29 @@ namespace AppInstaller::Repository::SQLite Statement::~Statement() { - sqlite3_finalize(_stmt); + sqlite3_finalize(m_stmt); } bool Statement::Step(bool failFastOnError) { - int result = sqlite3_step(_stmt); + AICLI_LOG(SQL, Verbose, << "Stepping statement #" << m_id); + int result = sqlite3_step(m_stmt); if (result == SQLITE_ROW) { - _state = State::HasRow; + AICLI_LOG(SQL, Verbose, << "Statement #" << m_id << " has data"); + m_state = State::HasRow; return true; } else if (result == SQLITE_DONE) { - _state = State::Completed; + AICLI_LOG(SQL, Verbose, << "Statement #" << m_id << " has completed"); + m_state = State::Completed; return false; } else { - _state = State::Error; + m_state = State::Error; if (failFastOnError) { FAIL_FAST_MSG("Critical SQL statement failed"); @@ -122,20 +139,22 @@ namespace AppInstaller::Repository::SQLite void Statement::Reset() { + AICLI_LOG(SQL, Verbose, << "Reset statement #" << m_id); // Ignore return value from reset, as if it is an error, it was the error from the last call to step. - sqlite3_reset(_stmt); - _state = State::Prepared; + sqlite3_reset(m_stmt); + m_state = State::Prepared; } Savepoint::Savepoint(Connection& connection, std::string&& name) : - _name(std::move(name)) + m_name(std::move(name)) { using namespace std::string_literals; Statement begin = Statement::Create(connection, "SAVEPOINT ["s + name + "]"); - _rollback = Statement::Create(connection, "ROLLBACK TO ["s + name + "]", true); - _commit = Statement::Create(connection, "RELEASE ["s + name + "]", true); + m_rollback = Statement::Create(connection, "ROLLBACK TO ["s + name + "]", true); + m_commit = Statement::Create(connection, "RELEASE ["s + name + "]", true); + AICLI_LOG(SQL, Info, << "Begin savepoint: " << m_name); begin.Step(); } @@ -151,19 +170,21 @@ namespace AppInstaller::Repository::SQLite void Savepoint::Rollback() { - if (_inProgress) + if (m_inProgress) { - _rollback.Step(true); - _inProgress = false; + AICLI_LOG(SQL, Info, << "Roll back savepoint: " << m_name); + m_rollback.Step(true); + m_inProgress = false; } } void Savepoint::Commit() { - if (_inProgress) + if (m_inProgress) { - _commit.Step(true); - _inProgress = false; + AICLI_LOG(SQL, Info, << "Commit savepoint: " << m_name); + m_commit.Step(true); + m_inProgress = false; } } } diff --git a/src/AppInstallerRepositoryCore/SQLiteWrapper.h b/src/AppInstallerRepositoryCore/SQLiteWrapper.h @@ -84,17 +84,17 @@ namespace AppInstaller::Repository::SQLite Connection(const Connection&) = delete; Connection& operator=(const Connection&) = delete; - Connection(Connection&& other) noexcept { std::swap(_dbconn, other._dbconn); } - Connection& operator=(Connection&& other) noexcept { std::swap(_dbconn, other._dbconn); return *this; } + Connection(Connection&& other) noexcept { std::swap(m_dbconn, other.m_dbconn); } + Connection& operator=(Connection&& other) noexcept { std::swap(m_dbconn, other.m_dbconn); return *this; } ~Connection(); - operator sqlite3* () const { return _dbconn; } + operator sqlite3* () const { return m_dbconn; } private: Connection(const std::string& target, OpenDisposition disposition, OpenFlags flags); - sqlite3* _dbconn = nullptr; + sqlite3* m_dbconn = nullptr; }; // A SQL statement. @@ -107,12 +107,12 @@ namespace AppInstaller::Repository::SQLite Statement(const Statement&) = delete; Statement& operator=(const Statement&) = delete; - Statement(Statement&& other) noexcept { std::swap(_stmt, other._stmt); std::swap(_state, other._state); } - Statement& operator=(Statement&& other) noexcept { std::swap(_stmt, other._stmt); std::swap(_state, other._state); return *this; } + Statement(Statement&& other) noexcept { std::swap(m_stmt, other.m_stmt); std::swap(m_state, other.m_state); } + Statement& operator=(Statement&& other) noexcept { std::swap(m_stmt, other.m_stmt); std::swap(m_state, other.m_state); return *this; } ~Statement(); - operator sqlite3_stmt* () const { return _stmt; } + operator sqlite3_stmt* () const { return m_stmt; } // The state of the statement. enum class State @@ -128,14 +128,14 @@ namespace AppInstaller::Repository::SQLite }; // Gets the current state of the statement. - State GetState() const { return _state; } + State GetState() const { return m_state; } // Bind parameters to the statement. // The index is 1 based. template <typename Value> void Bind(int index, Value&& v) { - details::ParameterSpecifics<Value>::Bind(_stmt, index, std::forward<Value>(v)); + details::ParameterSpecifics<Value>::Bind(m_stmt, index, std::forward<Value>(v)); } // Evaluate the statement; either retrieving the next row or executing some action. @@ -148,8 +148,8 @@ namespace AppInstaller::Repository::SQLite template <typename Value> Value GetColumn(int column) { - THROW_HR_IF(E_BOUNDS, _state != State::HasRow); - return details::ParameterSpecifics<Value>::GetColumn(_stmt, column); + THROW_HR_IF(E_BOUNDS, m_state != State::HasRow); + return details::ParameterSpecifics<Value>::GetColumn(m_stmt, column); } // Gets the entire row of values from the current row. @@ -174,12 +174,13 @@ namespace AppInstaller::Repository::SQLite template <typename... Values, int... I> std::tuple<Values...> GetRowImpl(std::integer_sequence<int, I...>) { - THROW_HR_IF(E_BOUNDS, _state != State::HasRow); - return std::make_tuple(details::ParameterSpecifics<Values>::GetColumn(_stmt, I)...); + THROW_HR_IF(E_BOUNDS, m_state != State::HasRow); + return std::make_tuple(details::ParameterSpecifics<Values>::GetColumn(m_stmt, I)...); } - sqlite3_stmt* _stmt = nullptr; - State _state = State::Prepared; + size_t m_id = 0; + sqlite3_stmt* m_stmt = nullptr; + State m_state = State::Prepared; }; // A SQLite savepoint. @@ -205,9 +206,9 @@ namespace AppInstaller::Repository::SQLite private: Savepoint(Connection& connection, std::string&& name); - std::string _name; - bool _inProgress = true; - Statement _rollback; - Statement _commit; + std::string m_name; + bool m_inProgress = true; + Statement m_rollback; + Statement m_commit; }; } diff --git a/src/AppInstallerRepositoryCore/pch.h b/src/AppInstallerRepositoryCore/pch.h @@ -5,9 +5,8 @@ #define NOMINMAX #include <windows.h> -#include "yaml-cpp/yaml.h" - -#include "TelemetryWrapper.h" +#include <AppInstallerLogging.h> +#include <yaml-cpp/yaml.h> #include <wil/result_macros.h> @@ -15,6 +14,7 @@ #include <winrt/Windows.Foundation.h> +#include <iomanip> #include <string> #include <stdexcept> #include <system_error> diff --git a/src/Telemetry/Telemetry.vcxitems b/src/Telemetry/Telemetry.vcxitems @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup Label="Globals"> - <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects> - <HasSharedItems>true</HasSharedItems> - <ItemsProjectGuid>{4b988559-ddbd-4456-9300-0c3aad12c466}</ItemsProjectGuid> - </PropertyGroup> - <ItemDefinitionGroup> - <ClCompile> - <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory)</AdditionalIncludeDirectories> - </ClCompile> - </ItemDefinitionGroup> - <ItemGroup> - <ProjectCapability Include="SourceItemsFromImports" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="$(MSBuildThisFileDirectory)TelemetryWrapper.cpp" /> - <ClCompile Include="$(MSBuildThisFileDirectory)TraceLogging.cpp" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="$(MSBuildThisFileDirectory)MicrosoftTelemetry.h" /> - <ClInclude Include="$(MSBuildThisFileDirectory)TelemetryWrapper.h" /> - <ClInclude Include="$(MSBuildThisFileDirectory)TraceLogging.h" /> - <ClInclude Include="$(MSBuildThisFileDirectory)WinEventLogLevels.h" /> - </ItemGroup> -</Project>- \ No newline at end of file diff --git a/src/Telemetry/TelemetryWrapper.cpp b/src/Telemetry/TelemetryWrapper.cpp @@ -1,40 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#include "pch.h" -#include "TelemetryWrapper.h" - -#define PKGMGR_CLIENT_EVENT_INFO "Information" -#define PKGMGR_CLIENT_MESSAGE "Message" - -namespace AppInstaller::CLI -{ - TelemetryTraceLogger::TelemetryTraceLogger() - { - RegisterTraceLogging(); - } - - TelemetryTraceLogger::~TelemetryTraceLogger() - { - UnRegisterTraceLogging(); - } - - TelemetryTraceLogger& TelemetryTraceLogger::GetInstance() - { - static TelemetryTraceLogger instance; - return instance; - } - - void TelemetryTraceLogger::LogMessage(std::wstring_view message) - { - if (g_IsTelemetryProviderEnabled) - { - TraceLoggingWrite(g_hTelemetryProvider, - PKGMGR_CLIENT_EVENT_INFO, - TraceLoggingCountedWideString(message.data(), static_cast<ULONG>(message.size()), PKGMGR_CLIENT_MESSAGE), - TelemetryPrivacyDataTag(PDT_ProductAndServicePerformance), - TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES)); - } - - //ToDo if required add logging to disk file here - } -}- \ No newline at end of file diff --git a/src/Telemetry/TelemetryWrapper.h b/src/Telemetry/TelemetryWrapper.h @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -#pragma once - -#include "TraceLogging.h" -#include <xstring> - -namespace AppInstaller::CLI -{ - class TelemetryTraceLogger - { - public: - static TelemetryTraceLogger& GetInstance(); - virtual void LogMessage(std::wstring_view message); - - private: - TelemetryTraceLogger(); - ~TelemetryTraceLogger(); - }; -}- \ No newline at end of file