diff --git a/DataSpec/SpecBase.cpp b/DataSpec/SpecBase.cpp
index aef52fa55..6fd2cf9c3 100644
--- a/DataSpec/SpecBase.cpp
+++ b/DataSpec/SpecBase.cpp
@@ -486,7 +486,7 @@ void SpecBase::copyBuildListData(std::vector<std::tuple<size_t, size_t, bool>>&
   int loadIdx = 0;
   for (const auto& tag : buildList) {
     hecl::SystemString str = fmt::format(FMT_STRING(_SYS_STR("Copying {}")), tag);
-    progress.print(str.c_str(), nullptr, ++loadIdx / float(buildList.size()));
+    progress.print(str, std::nullopt, ++loadIdx / float(buildList.size()));
 
     auto& [positionOut, sizeOut, compressedOut] = fileIndex.emplace_back();
 
diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp
index 0b87313ac..2180359d9 100644
--- a/DataSpec/SpecMP1.cpp
+++ b/DataSpec/SpecMP1.cpp
@@ -325,9 +325,8 @@ struct SpecMP1 : SpecBase {
     progress.startNewLine();
     progress.print(_SYS_STR("MP1 Root"), _SYS_STR(""), 0.0);
     int prog = 0;
-    ctx.progressCB = [&](std::string_view name, float) {
-      hecl::SystemStringConv nameView(name);
-      progress.print(_SYS_STR("MP1 Root"), nameView.c_str(), prog / (float)m_nonPaks.size());
+    ctx.progressCB = [&](nod::SystemStringView name, float) {
+      progress.print(_SYS_STR("MP1 Root"), name, prog / (float)m_nonPaks.size());
     };
     for (const nod::Node* node : m_nonPaks) {
       node->extractToDirectory(mp1OutPath.getAbsolutePath(), ctx);
@@ -367,7 +366,7 @@ struct SpecMP1 : SpecBase {
         int threadIdx = hecl::ClientProcess::GetThreadWorkerIdx();
         m_pakRouter.extractResources(pak, force, btok,
                                      [&progress, &pakName, threadIdx](const hecl::SystemChar* substr, float factor) {
-                                       progress.print(pakName.c_str(), substr, factor, threadIdx);
+                                       progress.print(pakName, substr, factor, threadIdx);
                                      });
       });
     }
diff --git a/DataSpec/SpecMP2.cpp b/DataSpec/SpecMP2.cpp
index e226ea999..8bda301a6 100644
--- a/DataSpec/SpecMP2.cpp
+++ b/DataSpec/SpecMP2.cpp
@@ -285,9 +285,8 @@ struct SpecMP2 : SpecBase {
     progress.startNewLine();
     progress.print(_SYS_STR("MP2 Root"), _SYS_STR(""), 0.0);
     int prog = 0;
-    ctx.progressCB = [&prog, &progress](std::string_view name, float) {
-      hecl::SystemStringConv nameView(name);
-      progress.print(_SYS_STR("MP2 Root"), nameView.c_str(), prog);
+    ctx.progressCB = [&prog, &progress](nod::SystemStringView name, float) {
+      progress.print(_SYS_STR("MP2 Root"), name, prog);
     };
     for (const nod::Node* node : m_nonPaks) {
       node->extractToDirectory(mp2OutPath.getAbsolutePath(), ctx);
@@ -310,7 +309,7 @@ struct SpecMP2 : SpecBase {
         int threadIdx = hecl::ClientProcess::GetThreadWorkerIdx();
         m_pakRouter.extractResources(pak, force, btok,
                                      [&progress, &pakName, threadIdx](const hecl::SystemChar* substr, float factor) {
-                                       progress.print(pakName.c_str(), substr, factor, threadIdx);
+                                       progress.print(pakName, substr, factor, threadIdx);
                                      });
       });
     }
diff --git a/DataSpec/SpecMP3.cpp b/DataSpec/SpecMP3.cpp
index 5c3dbb012..2256cddc6 100644
--- a/DataSpec/SpecMP3.cpp
+++ b/DataSpec/SpecMP3.cpp
@@ -372,9 +372,8 @@ struct SpecMP3 : SpecBase {
     hecl::SystemString currentTarget;
     size_t nodeCount = 0;
     int prog = 0;
-    nod::ExtractionContext ctx = {force, [&](std::string_view name, float) {
-                                    hecl::SystemStringConv nameView(name);
-                                    progress.print(currentTarget.c_str(), nameView.c_str(), prog / (float)nodeCount);
+    nod::ExtractionContext ctx = {force, [&](nod::SystemStringView name, float) {
+                                    progress.print(currentTarget, name, prog / (float)nodeCount);
                                   }};
     if (doMP3) {
       m_workPath.makeDir();
@@ -420,7 +419,7 @@ struct SpecMP3 : SpecBase {
         process.addLambdaTransaction([this, &progress, &pak, pakName, force](hecl::blender::Token& btok) {
           m_pakRouter.extractResources(pak, force, btok,
                                        [&progress, &pakName](const hecl::SystemChar* substr, float factor) {
-                                         progress.print(pakName.c_str(), substr, factor);
+                                         progress.print(pakName, substr, factor);
                                        });
         });
       }
@@ -470,7 +469,7 @@ struct SpecMP3 : SpecBase {
         process.addLambdaTransaction([this, &progress, &pak, pakName, force](hecl::blender::Token& btok) {
           m_fePakRouter.extractResources(pak, force, btok,
                                          [&progress, &pakName](const hecl::SystemChar* substr, float factor) {
-                                           progress.print(pakName.c_str(), substr, factor);
+                                           progress.print(pakName, substr, factor);
                                          });
         });
       }
diff --git a/hecl/driver/ToolImage.hpp b/hecl/driver/ToolImage.hpp
index 7e1b9cac5..7dc2d01e8 100644
--- a/hecl/driver/ToolImage.hpp
+++ b/hecl/driver/ToolImage.hpp
@@ -107,7 +107,7 @@ public:
       hecl::SystemString fileOut = hecl::SystemString(outPath.getAbsolutePath()) + _SYS_STR('/') + idView.c_str();
       hecl::MultiProgressPrinter printer(true);
       auto progFunc = [&printer](float totalProg, nod::SystemStringView fileName, size_t fileBytesXfered) {
-        printer.print(fileName.data(), nullptr, totalProg);
+        printer.print(fileName, std::nullopt, totalProg);
       };
       if (id[0] == 'G') {
         fileOut += _SYS_STR(".gcm");
diff --git a/hecl/include/hecl/MultiProgressPrinter.hpp b/hecl/include/hecl/MultiProgressPrinter.hpp
index 0eb9b508a..78292acdd 100644
--- a/hecl/include/hecl/MultiProgressPrinter.hpp
+++ b/hecl/include/hecl/MultiProgressPrinter.hpp
@@ -2,6 +2,7 @@
 
 #include <cstdint>
 #include <mutex>
+#include <optional>
 #include <thread>
 #include <vector>
 
@@ -55,7 +56,8 @@ class MultiProgressPrinter {
 public:
   MultiProgressPrinter(bool activate = false);
   ~MultiProgressPrinter();
-  void print(const hecl::SystemChar* message, const hecl::SystemChar* submessage, float factor = -1.f,
+  void print(std::optional<hecl::SystemStringView> message, std::optional<hecl::SystemStringView> submessage,
+             float factor = -1.f,
              int threadIdx = 0) const;
   void setMainFactor(float factor) const;
   void setMainIndeterminate(bool indeterminate) const;
diff --git a/hecl/lib/ClientProcess.cpp b/hecl/lib/ClientProcess.cpp
index 7b4c3a52a..d8b0aae77 100644
--- a/hecl/lib/ClientProcess.cpp
+++ b/hecl/lib/ClientProcess.cpp
@@ -184,7 +184,7 @@ bool ClientProcess::syncCook(const hecl::ProjectPath& path, Database::IDataSpec*
             str = fmt::format(FMT_STRING(_SYS_STR("Cooking {}")), path.getRelativePath());
           else
             str = fmt::format(FMT_STRING(_SYS_STR("Cooking {}|{}")), path.getRelativePath(), path.getAuxInfo());
-          m_progPrinter->print(str.c_str(), nullptr, -1.f, hecl::ClientProcess::GetThreadWorkerIdx());
+          m_progPrinter->print(str, std::nullopt, -1.f, hecl::ClientProcess::GetThreadWorkerIdx());
           m_progPrinter->flush();
         } else {
           if (path.getAuxInfo().empty())
@@ -199,7 +199,7 @@ bool ClientProcess::syncCook(const hecl::ProjectPath& path, Database::IDataSpec*
             str = fmt::format(FMT_STRING(_SYS_STR("Cooked  {}")), path.getRelativePath());
           else
             str = fmt::format(FMT_STRING(_SYS_STR("Cooked  {}|{}")), path.getRelativePath(), path.getAuxInfo());
-          m_progPrinter->print(str.c_str(), nullptr, -1.f, hecl::ClientProcess::GetThreadWorkerIdx());
+          m_progPrinter->print(str, std::nullopt, -1.f, hecl::ClientProcess::GetThreadWorkerIdx());
           m_progPrinter->flush();
         }
       }
diff --git a/hecl/lib/MultiProgressPrinter.cpp b/hecl/lib/MultiProgressPrinter.cpp
index 211e37de1..8a0aff17a 100644
--- a/hecl/lib/MultiProgressPrinter.cpp
+++ b/hecl/lib/MultiProgressPrinter.cpp
@@ -286,7 +286,9 @@ MultiProgressPrinter::~MultiProgressPrinter() {
     m_logThread.join();
 }
 
-void MultiProgressPrinter::print(const hecl::SystemChar* message, const hecl::SystemChar* submessage, float factor,
+void MultiProgressPrinter::print(std::optional<hecl::SystemStringView> message,
+                                 std::optional<hecl::SystemStringView> submessage,
+                                 float factor,
                                  int threadIdx) const {
   if (!m_running) {
     return;
@@ -302,12 +304,12 @@ void MultiProgressPrinter::print(const hecl::SystemChar* message, const hecl::Sy
 
   ThreadStat& stat = m_threadStats[threadIdx];
   if (message) {
-    stat.m_message = message;
+    stat.m_message = *message;
   } else {
     stat.m_message.clear();
   }
   if (submessage) {
-    stat.m_submessage = submessage;
+    stat.m_submessage = *submessage;
   } else {
     stat.m_submessage.clear();
   }
diff --git a/hecl/lib/Project.cpp b/hecl/lib/Project.cpp
index 99625fbf9..3c9a946d7 100644
--- a/hecl/lib/Project.cpp
+++ b/hecl/lib/Project.cpp
@@ -322,7 +322,7 @@ public:
     submsg += _SYS_STR(" (");
     submsg += specEnt->m_name.data();
     submsg += _SYS_STR(')');
-    m_progPrinter.print(m_dir, submsg.c_str(), m_prog);
+    m_progPrinter.print(m_dir, submsg, m_prog);
   }
   void reportFile(const DataSpecEntry* specEnt, const SystemChar* extra) {
     SystemString submsg(m_file);
@@ -331,9 +331,9 @@ public:
     submsg += _SYS_STR(", ");
     submsg += extra;
     submsg += _SYS_STR(')');
-    m_progPrinter.print(m_dir, submsg.c_str(), m_prog);
+    m_progPrinter.print(m_dir, submsg, m_prog);
   }
-  void reportDirComplete() { m_progPrinter.print(m_dir, nullptr, 1.f); }
+  void reportDirComplete() { m_progPrinter.print(m_dir, std::nullopt, 1.f); }
 };
 
 static void VisitFile(const ProjectPath& path, bool force, bool fast,