From 31c14f2ad3714c262108acf6613ab023bc971012 Mon Sep 17 00:00:00 2001 From: ayousuf23 <72010390+ayousuf23@users.noreply.github.com> Date: Mon, 21 Feb 2022 13:02:30 -0500 Subject: [PATCH] Updated background invocation `&` operator to use `-WorkingDirectory` when starting a new job (#16180) --- .../engine/runtime/Operations/MiscOps.cs | 31 ++++++++++++------- .../Microsoft.PowerShell.Core/Job.Tests.ps1 | 12 ++++++- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs b/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs index 62468dcfc3fe..72a676dad1cc 100644 --- a/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs +++ b/src/System.Management.Automation/engine/runtime/Operations/MiscOps.cs @@ -531,12 +531,8 @@ private static string GetParameterText(string parameterName) var pipelineOffset = pipelineAst.Extent.StartOffset; var variables = pipelineAst.FindAll(static x => x is VariableExpressionAst, true); - // Used to make sure that the job runs in the current directory - const string cmdPrefix = @"Microsoft.PowerShell.Management\Set-Location -LiteralPath $using:pwd ; "; - - // Minimize allocations by initializing the stringbuilder to the size of the source string + prefix + space for ${using:} * 2 - System.Text.StringBuilder updatedScriptblock = new System.Text.StringBuilder(cmdPrefix.Length + scriptblockBodyString.Length + 18); - updatedScriptblock.Append(cmdPrefix); + // Minimize allocations by initializing the stringbuilder to the size of the source string + space for ${using:} * 2 + System.Text.StringBuilder updatedScriptblock = new System.Text.StringBuilder(scriptblockBodyString.Length + 18); int position = 0; // Prefix variables in the scriptblock with $using: @@ -568,14 +564,25 @@ private static string GetParameterText(string parameterName) var sb = ScriptBlock.Create(updatedScriptblock.ToString()); var commandInfo = new CmdletInfo("Start-Job", typeof(StartJobCommand)); commandProcessor = context.CommandDiscovery.LookupCommandProcessor(commandInfo, CommandOrigin.Internal, false, context.EngineSessionState); - var parameter = CommandParameterInternal.CreateParameterWithArgument( + + var workingDirectoryParameter = CommandParameterInternal.CreateParameterWithArgument( parameterAst: pipelineAst, - "ScriptBlock", - null, + parameterName: "WorkingDirectory", + parameterText: null, argumentAst: pipelineAst, - sb, - false); - commandProcessor.AddParameter(parameter); + value: context.SessionState.Path.CurrentLocation.Path, + spaceAfterParameter: false); + + var scriptBlockParameter = CommandParameterInternal.CreateParameterWithArgument( + parameterAst: pipelineAst, + parameterName: "ScriptBlock", + parameterText: null, + argumentAst: pipelineAst, + value: sb, + spaceAfterParameter: false); + + commandProcessor.AddParameter(workingDirectoryParameter); + commandProcessor.AddParameter(scriptBlockParameter); pipelineProcessor.Add(commandProcessor); pipelineProcessor.LinkPipelineSuccessOutput(outputPipe ?? new Pipe(new List())); diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/Job.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/Job.Tests.ps1 index 90477267b4e6..2cf4f04dde08 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/Job.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/Job.Tests.ps1 @@ -178,7 +178,7 @@ Describe "Debug-job test" -Tag "Feature" { } } -Describe "Ampersand background test" -Tag "CI","Slow" { +Describe "Ampersand background test" -Tag "CI", "Slow" { Context "Simple background job" { AfterEach { Get-Job | Remove-Job -Force @@ -218,6 +218,16 @@ Describe "Ampersand background test" -Tag "CI","Slow" { $j = Get-Location | ForEach-Object -MemberName Path & Receive-Job -Wait $j | Should -Be ($PWD.Path) } + It "Make sure Set-Location is not used in the job's script block to set the working directory" { + $j = (Get-Variable -Value ExecutionContext).SessionState.PSVariable.Get("MyInvocation").Value.MyCommand.ScriptBlock & + (Receive-Job -Wait $j).ToString() | Should -BeExactly "(Get-Variable -Value ExecutionContext).SessionState.PSVariable.Get(`"MyInvocation`").Value.MyCommand.ScriptBlock" + } + It "Test that changing working directory also changes background job's working directory" { + Set-Location .. + $WorkingDirectory = (Get-Location).ToString() + $BackgroundJob = (Get-Location &) + (Receive-Job -Wait $BackgroundJob).ToString() | Should -BeExactly $WorkingDirectory + } It "Test that output redirection is done in the background job" { $j = Write-Output hello > $TESTDRIVE/hello.txt & Receive-Job -Wait $j | Should -BeNullOrEmpty