diff --git a/azure-pipelines/vmr-sb-validation.yml b/azure-pipelines/vmr-sb-validation.yml
index dbbac51897b..f60df5fa050 100644
--- a/azure-pipelines/vmr-sb-validation.yml
+++ b/azure-pipelines/vmr-sb-validation.yml
@@ -29,7 +29,7 @@ resources:
- repository: vmr
type: github
name: dotnet/dotnet
- endpoint: dotnet
+ endpoint: public
stages:
- template: /eng/pipelines/templates/stages/vmr-build.yml@vmr
diff --git a/eng/Versions.props b/eng/Versions.props
index 4a7d92089b8..e4f9bbfb7b6 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -3,7 +3,7 @@
- 18.7.11release
+ 18.7.12release
servicing
18.6.0-preview-26180-08
15.1.0.0
diff --git a/src/Framework/NativeMethods.cs b/src/Framework/NativeMethods.cs
index cf1c317cee4..f935286d1c7 100644
--- a/src/Framework/NativeMethods.cs
+++ b/src/Framework/NativeMethods.cs
@@ -1496,15 +1496,18 @@ internal static List> GetChildProcessIds(in
/// Internal, optimized GetCurrentDirectory implementation that simply delegates to the native method
///
///
- internal static unsafe string GetCurrentDirectory()
+ internal static string GetCurrentDirectory()
{
#if FEATURE_LEGACY_GETCURRENTDIRECTORY
if (IsWindows)
{
- int bufferSize = GetCurrentDirectoryWin32(0, null);
- char* buffer = stackalloc char[bufferSize];
- int pathLength = GetCurrentDirectoryWin32(bufferSize, buffer);
- return new string(buffer, startIndex: 0, length: pathLength);
+ unsafe
+ {
+ int bufferSize = GetCurrentDirectoryWin32(0, null);
+ char* buffer = stackalloc char[bufferSize];
+ int pathLength = GetCurrentDirectoryWin32(bufferSize, buffer);
+ return new string(buffer, startIndex: 0, length: pathLength);
+ }
}
#endif
return Directory.GetCurrentDirectory();
diff --git a/src/MSBuild.Bootstrap.Utils/Tasks/InstallDotNetCoreTask.cs b/src/MSBuild.Bootstrap.Utils/Tasks/InstallDotNetCoreTask.cs
index 9606b11002d..15d35446d8a 100644
--- a/src/MSBuild.Bootstrap.Utils/Tasks/InstallDotNetCoreTask.cs
+++ b/src/MSBuild.Bootstrap.Utils/Tasks/InstallDotNetCoreTask.cs
@@ -154,13 +154,32 @@ private ScriptExecutionSettings SetupScriptsExecutionSettings()
{
string scriptExtension = IsWindows ? "ps1" : "sh";
string scriptPath = Path.Combine(DotNetInstallScriptRootPath, $"{ScriptName}.{scriptExtension}");
+ // On Windows the native command-line parser treats a backslash before the closing quote as
+ // escaping it (e.g. "C:\dir\" becomes C:\dir"), so trim a trailing separator before quoting.
+ string installDir = TrimTrailingDirectorySeparators(InstallDir);
string scriptArgs = IsWindows
- ? $"-NoProfile -ExecutionPolicy Bypass -File {scriptPath} -Version {Version} -InstallDir {InstallDir}"
- : $"{scriptPath} --version {Version} --install-dir {InstallDir}";
+ ? $"-NoProfile -ExecutionPolicy Bypass -File \"{scriptPath}\" -Version {Version} -InstallDir \"{installDir}\""
+ : $"\"{scriptPath}\" --version {Version} --install-dir \"{installDir}\"";
return new ScriptExecutionSettings($"{ScriptName}.{scriptExtension}", scriptPath, scriptArgs);
}
+ ///
+ /// Trims trailing directory separators while preserving a path root (e.g. "C:\").
+ ///
+ private static string TrimTrailingDirectorySeparators(string path)
+ {
+ string root = Path.GetPathRoot(path) ?? string.Empty;
+ while (path.Length > root.Length &&
+ (path[path.Length - 1] == Path.DirectorySeparatorChar ||
+ path[path.Length - 1] == Path.AltDirectorySeparatorChar))
+ {
+ path = path.Substring(0, path.Length - 1);
+ }
+
+ return path;
+ }
+
///
/// A private struct to hold settings for script execution.
///