diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index 04a6cac6c9..cc06123032 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -233,6 +233,7 @@ cdpx
cdpxwin
cend
CENTERALIGN
+cerr
cfg
Cfg
changecursor
diff --git a/PowerToys.sln b/PowerToys.sln
index 3250682df6..83317057c7 100644
--- a/PowerToys.sln
+++ b/PowerToys.sln
@@ -271,6 +271,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest-ColorPickerUI", "s
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logging", "src\logging\logging.vcxproj", "{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logger", "src\common\logger\logger.vcxproj", "{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -549,6 +551,10 @@ Global
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.Build.0 = Debug|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.ActiveCfg = Release|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.Build.0 = Release|x64
+ {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.ActiveCfg = Debug|x64
+ {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.Build.0 = Debug|x64
+ {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.ActiveCfg = Release|x64
+ {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -628,6 +634,7 @@ Global
{4FA206A5-F69F-4193-BF8F-F6EEB496734C} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1} = {1D78B84B-CA39-406C-98F4-71F7EC266CC0}
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F} = {1AFB6476-670D-4E80-A464-657E01DFF482}
+ {D9B8FC84-322A-4F9F-BBB9-20915C47DDFD} = {1AFB6476-670D-4E80-A464-657E01DFF482}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
diff --git a/deps/spdlog.props b/deps/spdlog.props
index 921cf9509a..85b16b962c 100644
--- a/deps/spdlog.props
+++ b/deps/spdlog.props
@@ -3,7 +3,7 @@
$(MSBuildThisFileDirectory)spdlog\include;%(AdditionalIncludeDirectories)
- SPDLOG_WCHAR_TO_UTF8_SUPPORT;SPDLOG_COMPILED_LIB;%(PreprocessorDefinitions)
+ SPDLOG_WCHAR_TO_UTF8_SUPPORT;SPDLOG_COMPILED_LIB;SPDLOG_WCHAR_FILENAMES;%(PreprocessorDefinitions)
diff --git a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp
index 24a2d54a86..a7ab40cb69 100644
--- a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp
+++ b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp
@@ -18,6 +18,7 @@ auto Strings = create_notifications_strings();
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
+
namespace // Strings in this namespace should not be localized
{
const wchar_t APPLICATION_ID[] = L"PowerToysInstaller";
@@ -61,7 +62,7 @@ void setup_log(fs::path directory, const spdlog::level::level_enum severity)
std::shared_ptr logger;
if (severity != spdlog::level::off)
{
- logger = spdlog::basic_logger_mt("file", (directory / LOG_FILENAME).string());
+ logger = spdlog::basic_logger_mt("file", (directory / LOG_FILENAME).wstring());
std::error_code _;
const DWORD msiSev = severity == spdlog::level::debug ? INSTALLLOGMODE_VERBOSE : INSTALLLOGMODE_ERROR;
diff --git a/src/common/logger/framework.h b/src/common/logger/framework.h
new file mode 100644
index 0000000000..ce94278880
--- /dev/null
+++ b/src/common/logger/framework.h
@@ -0,0 +1,3 @@
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
diff --git a/src/common/logger/logger.cpp b/src/common/logger/logger.cpp
new file mode 100644
index 0000000000..7fb3e474c3
--- /dev/null
+++ b/src/common/logger/logger.cpp
@@ -0,0 +1,64 @@
+// logger.cpp : Defines the functions for the static library.
+//
+#include "pch.h"
+#include "framework.h"
+#include "logger.h"
+#include "logger_settings.h"
+#include