From 988c4d848cad1b9faa717df788d900b035bc3c8f Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Fri, 7 Aug 2026 14:54:17 -0500 Subject: [PATCH 1/2] Add quotes around Nullsoft Location Switch --- doc/ReleaseNotes.md | 1 + src/AppInstallerCommonCore/Manifest/ManifestCommon.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/ReleaseNotes.md b/doc/ReleaseNotes.md index a468b60c74..637ceccfa1 100644 --- a/doc/ReleaseNotes.md +++ b/doc/ReleaseNotes.md @@ -9,3 +9,4 @@ Added a new `--ignore-unavailable` flag to the `install` command. When installin * Fixed an issue where `winget search --id ` could fail to return a Microsoft Store package unless `--exact` was also provided. * Updated NUnit to v4 * Fixed a crash (`0x8000ffff`) when using `--disable-interactivity` with the Resume experimental feature enabled during install operations. +* Location parameter is now passed in quotes for Nullsoft Installers by default diff --git a/src/AppInstallerCommonCore/Manifest/ManifestCommon.cpp b/src/AppInstallerCommonCore/Manifest/ManifestCommon.cpp index 18fb24e5fa..98341e7c8d 100644 --- a/src/AppInstallerCommonCore/Manifest/ManifestCommon.cpp +++ b/src/AppInstallerCommonCore/Manifest/ManifestCommon.cpp @@ -1049,7 +1049,7 @@ namespace AppInstaller::Manifest { {InstallerSwitchType::Silent, ManifestInstaller::string_t("/S")}, {InstallerSwitchType::SilentWithProgress, ManifestInstaller::string_t("/S")}, - {InstallerSwitchType::InstallLocation, ManifestInstaller::string_t("/D=" + std::string(ARG_TOKEN_INSTALLPATH))} + {InstallerSwitchType::InstallLocation, ManifestInstaller::string_t("/D=\"" + std::string(ARG_TOKEN_INSTALLPATH) + "\"")} }; case InstallerTypeEnum::Inno: return From 4d0b8044782115e636c92a93c47b1c453ca4c4cc Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Fri, 7 Aug 2026 14:57:28 -0500 Subject: [PATCH 2/2] Add test for Nullsoft installer location switch quoting Verify that a --location value containing spaces (e.g. C:\Program Files\CustomInstallDir) is properly quoted in the /D= switch produced for Nullsoft installers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../AppInstallerCLITests.vcxproj | 3 +++ .../AppInstallerCLITests.vcxproj.filters | 3 +++ src/AppInstallerCLITests/InstallFlow.cpp | 15 +++++++++++++++ .../InstallerArgTest_Nullsoft_NoSwitches.yaml | 12 ++++++++++++ 4 files changed, 33 insertions(+) create mode 100644 src/AppInstallerCLITests/TestData/InstallerArgTest_Nullsoft_NoSwitches.yaml diff --git a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj index 2b740c84e1..4a3b177f82 100644 --- a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj +++ b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj @@ -474,6 +474,9 @@ true + + true + true diff --git a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters index 29debf6a13..f9eda86c51 100644 --- a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters +++ b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj.filters @@ -795,6 +795,9 @@ TestData + + TestData + TestData diff --git a/src/AppInstallerCLITests/InstallFlow.cpp b/src/AppInstallerCLITests/InstallFlow.cpp index 88e1a8f89f..bab0632aed 100644 --- a/src/AppInstallerCLITests/InstallFlow.cpp +++ b/src/AppInstallerCLITests/InstallFlow.cpp @@ -956,6 +956,21 @@ TEST_CASE("ShellExecuteHandlerInstallerArgs", "[InstallFlow][workflow]") REQUIRE(installerArgs.find("\t") == std::string::npos); // Whitespace only Custom switches should not be appended } + { + std::ostringstream installOutput; + TestContext context{ installOutput, std::cin }; + auto previousThreadGlobals = context.SetForCurrentThread(); + // Nullsoft type with --location containing spaces; verify value is quoted in /D= switch + auto manifest = YamlParser::CreateFromPath(TestDataFile("InstallerArgTest_Nullsoft_NoSwitches.yaml")); + context.Args.AddArg(Execution::Args::Type::Silent); + context.Args.AddArg(Execution::Args::Type::InstallLocation, R"(C:\Program Files\CustomInstallDir)"sv); + context.Add(manifest); + context.Add(manifest.Installers.at(0)); + context << GetInstallerArgs; + std::string installerArgs = context.Get(); + REQUIRE(installerArgs.find(R"(/D="C:\Program Files\CustomInstallDir")") != std::string::npos); + } + { std::ostringstream installOutput; TestContext context{ installOutput, std::cin }; diff --git a/src/AppInstallerCLITests/TestData/InstallerArgTest_Nullsoft_NoSwitches.yaml b/src/AppInstallerCLITests/TestData/InstallerArgTest_Nullsoft_NoSwitches.yaml new file mode 100644 index 0000000000..ccccc711cc --- /dev/null +++ b/src/AppInstallerCLITests/TestData/InstallerArgTest_Nullsoft_NoSwitches.yaml @@ -0,0 +1,12 @@ +Id: AppInstallerCliTest.TestInstaller +Version: 1.0.0.0 +Name: AppInstaller Test Installer +Publisher: Microsoft Corporation +AppMoniker: AICLITest +License: Test +Installers: + - Arch: x64 + Url: https://ThisIsNotUsed + InstallerType: nullsoft + Sha256: 65DB2F2AC2686C7F2FD69D4A4C6683B888DC55BFA20A0E32CA9F838B51689A3B +ManifestVersion: 0.1.0