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. ///