Update:
- It seems that in v7.1+ the previously missing env. vars. on Windows are now present (but they'll continue to be missing in Windows PowerShell); on Unix-like platforms, the resulting environment is still virtually empty as of v7.5.x.
On both Windows and Unix platforms, Start-Process -UseNewEnvironment results in an environment that is missing crucial standard environment variables, making the new environment virtually useless, while not providing a mechanism to define a new environment:
-
On Windows, -UseNewEnvironment defines only the variables that are explicitly defined, as displayed in System Properties (sysdm.cpl), with crucial, usually automatically defined variables such as $env:ProgramFiles missing, and $env:USERNAME unexpectedly containing SYSTEM.
-
On Unix, an empty environment is essentially passed (with no environment variables defined at all, except $env:PSModulePath).
-
This even prevents invoking any executable by filename only, given that $env:PATH is undefined - see below.
-
While this behavior is similar to POSIX env -i on Unix platforms, the env utility notably includes a mechanism to provide a new environment via name=value pairs, which Start-Process lacks.
Possible solutions:
-
Repurpose -UseNewEnvironment to not start with a blank slate / crucial variables missing, but to provide the same environment that a shell would see when directly launched by the system (in other words: any environment-variable modifications made by the calling shell would be ignored).
-
Additionally, provide a way to pass a custom environment, applied on top of the current or pristine (-UseNewEnvironment) environment:
-
E.g., a new -Environment <hashtable> / -Environment <Collections.DictionaryEntry[]> parameter could be used.
-
If someone truly wanted an empty environment, they could start with $emptyEnv = (Get-ChildItem env:); $emptyEnv | % { $_.Value = $null } and pass -Environment $emptyEnv.
The -Environment feature would allow for an - incomplete - approximation of the convenient ad-hoc, command-scoped environment-variable definition feature that POSIX-like shells such as bash offer, where you can prepend one or more name=value pairs to a command:
# Bash (any POSIX-compatible shell)
# Defines $env:FOO as 'bar', but *only for the some-utility child process*.
FOO=bar some-utility 666
Update: #3316 suggests emulating this syntax in PowerShell, which would be the best solution.
The PS approximation would be:
Start-Process -Wait -Environment @{ FOO = 'bar' } some-utility -Args 666
That said, a crucial limitation is that use of Start-Process makes the external utility operate outside PowerShell's streams, so the only way to provide input / collect output is via the -Redirect* parameters, which requires auxiliary files.
Current behavior
Start-Process -UseNewEnvironment -Wait -NoNewWindow pwsh -args '-Command', 'gci env:; whoami'
Internal Windows PowerShell error. Loading managed Windows PowerShell failed with error 8009001d.
- On Unix: PowerShell starts, lists
$env:PSModulePath as the only environment variable - with a seemingly temporary user account's module directory prepended - and the whoami invocation fails, because it cannot be located in the absence of a suitable $env:PATH.
Name Value
---- -----
PSModulePath /tmp/ba38e79f-40c2-440e-ae08-7cf32e0708e1/.local/share/powershell/Modules:/usr/local/share/powershell/Modules:/opt/microsoft/...
whoami : The term 'whoami' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path
was included, verify that the path is correct and try again.
At line:1 char:21
+ Get-ChildItem env:; whoami
+ ~~~~~~
+ CategoryInfo : ObjectNotFound: (whoami:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Environment data
PowerShell Core v6.0.0-beta.5 on macOS 10.12.6
PowerShell Core v6.0.0-beta.5 on Ubuntu 16.04.3 LTS
PowerShell Core v6.0.0-beta.5 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Windows PowerShell v5.1.15063.483 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Update:
On both Windows and Unix platforms,
Start-Process -UseNewEnvironmentresults in an environment that is missing crucial standard environment variables, making the new environment virtually useless, while not providing a mechanism to define a new environment:On Windows,
-UseNewEnvironmentdefines only the variables that are explicitly defined, as displayed in System Properties (sysdm.cpl), with crucial, usually automatically defined variables such as$env:ProgramFilesmissing, and$env:USERNAMEunexpectedly containingSYSTEM.powershellinstance from being started this way - see Start-Process fails to launch new powershell.exe instance with -UseNewEnvironment switch #3545 (comment) and below.On Unix, an empty environment is essentially passed (with no environment variables defined at all, except
$env:PSModulePath).This even prevents invoking any executable by filename only, given that
$env:PATHis undefined - see below.While this behavior is similar to POSIX
env -ion Unix platforms, theenvutility notably includes a mechanism to provide a new environment vianame=valuepairs, whichStart-Processlacks.Possible solutions:
Repurpose
-UseNewEnvironmentto not start with a blank slate / crucial variables missing, but to provide the same environment that a shell would see when directly launched by the system (in other words: any environment-variable modifications made by the calling shell would be ignored).Additionally, provide a way to pass a custom environment, applied on top of the current or pristine (
-UseNewEnvironment) environment:E.g., a new
-Environment <hashtable>/-Environment <Collections.DictionaryEntry[]>parameter could be used.If someone truly wanted an empty environment, they could start with
$emptyEnv = (Get-ChildItem env:); $emptyEnv | % { $_.Value = $null }and pass-Environment $emptyEnv.The
-Environmentfeature would allow for an - incomplete - approximation of the convenient ad-hoc, command-scoped environment-variable definition feature that POSIX-like shells such asbashoffer, where you can prepend one or morename=valuepairs to a command:Update: #3316 suggests emulating this syntax in PowerShell, which would be the best solution.
The PS approximation would be:
That said, a crucial limitation is that use of
Start-Processmakes the external utility operate outside PowerShell's streams, so the only way to provide input / collect output is via the-Redirect*parameters, which requires auxiliary files.Current behavior
-LoadUserProfilemakes no difference.$env:PSModulePathas the only environment variable - with a seemingly temporary user account's module directory prepended - and thewhoamiinvocation fails, because it cannot be located in the absence of a suitable$env:PATH.Environment data