diff --git a/src/System.Management.Automation/engine/Modules/SwitchProcessCommand.cs b/src/System.Management.Automation/engine/Modules/SwitchProcessCommand.cs index 8ce2f08d84..31f3376d74 100644 --- a/src/System.Management.Automation/engine/Modules/SwitchProcessCommand.cs +++ b/src/System.Management.Automation/engine/Modules/SwitchProcessCommand.cs @@ -4,6 +4,7 @@ #nullable enable using System; +using System.Collections; using System.Collections.Generic; using System.Management.Automation; using System.Runtime.InteropServices; @@ -69,9 +70,19 @@ namespace Microsoft.PowerShell.Commands // need null terminator at end execArgs[execArgs.Length - 1] = null; + var env = Environment.GetEnvironmentVariables(); + var envBlock = new string?[env.Count + 1]; + int j = 0; + foreach (DictionaryEntry entry in env) + { + envBlock[j++] = entry.Key + "=" + entry.Value; + } + + envBlock[envBlock.Length - 1] = null; + // setup termios for a child process as .NET modifies termios dynamically for use with ReadKey() ConfigureTerminalForChildProcess(true); - int exitCode = Exec(command.Source, execArgs); + int exitCode = Exec(command.Source, execArgs, envBlock); if (exitCode < 0) { ConfigureTerminalForChildProcess(false); @@ -101,15 +112,18 @@ namespace Microsoft.PowerShell.Commands /// The arguments to send through to the executable. /// Array must have its final element be null. /// + /// + /// The environment variables to send through to the executable in the form of "key=value". + /// Array must have its final element be null. /// /// An exit code if exec failed, but if successful the calling process will be overwritten. /// [DllImport("libc", - EntryPoint = "execv", + EntryPoint = "execve", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true)] - private static extern int Exec(string path, string?[] args); + private static extern int Exec(string path, string?[] args, string?[] env); // leverage .NET runtime's native library which abstracts the need to handle different OS and architectures for termios api [DllImport("libSystem.Native", EntryPoint = "SystemNative_ConfigureTerminalForChildProcess")] diff --git a/test/powershell/Modules/Microsoft.PowerShell.Core/Exec.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Core/Exec.Tests.ps1 index 858a04fb4e..1a1023f0ea 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Core/Exec.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Core/Exec.Tests.ps1 @@ -48,6 +48,11 @@ Describe 'Switch-Process tests for Unix' -Tags 'CI' { ($p | Get-Process).Name -eq 'sleep' } -timeout 60000 -interval 100 | Should -BeTrue } + + It 'The environment will be copied to the child process' { + $env = pwsh -noprofile -outputformat text -command { $env:TEST_FOO='my test = value'; Switch-Process bash -c 'echo $TEST_FOO' } + $env | Should -BeExactly 'my test = value' + } } Describe 'Switch-Process for Windows' -Tag 'CI' {