-
Notifications
You must be signed in to change notification settings - Fork 124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add RFC for process environment blocks #384
base: master
Are you sure you want to change the base?
Conversation
Adds the RFC to support specifying environment variable(s) that are only set on subprocesses. This is to support a feature that is currently preset on sh based shells like bash but is not possible in PowerShell without more verbose code or other limitations.
When I contributed to this area, my plan was to first add new functionality like the |
I think this only applies to key names with 1 or more instances of Here's some cases where a bad actor could replace a key, or remove one -- depending on the keys order.
For example $vars = @{
"Path" = "/foo/bar"
"Path`u{0}`u{0}" = ''
"Some`u{0}LongName" = 'Trunc'
} Remove-Item Env:Some*
[Environment]::SetEnvironmentVariable( "SomePath", '/path' )
[Environment]::SetEnvironmentVariable( "SomePath`u{0}`u{0}", 'new' )
[Environment]::SetEnvironmentVariable( "Some`u{0}LongName", 'Trunc' )
Gci "env:\Some*" |Ft -AutoSize
Name Value
---- -----
SomePath new
Some Trunc Other control chars like Remove-Item Env:Some*
[Environment]::SetEnvironmentVariable( "SomePath", '/path' )
[Environment]::SetEnvironmentVariable( "SomePath`u{4}", 'new' )
Gci "env:\Some*" |Ft -AutoSize
Name Value
---- -----
SomePath /path
SomePath␄ new If the edge case is specifically from: https://gist.github.com/ninmonkey/c6bb4dc838e55e4581f86f86e0989f49 Update: It's a little more than trimmingNote that it maps
remove-item env:\*some*
[Environment]::SetEnvironmentVariable( "SomePath", 'one' )
[Environment]::SetEnvironmentVariable( "SomePath`u{0}`u{0}", 'two' )
[Environment]::SetEnvironmentVariable( "Some`u{0}Path`u{0}`u{0}", 'three' )
Gci "env:\*Some*"|Ft -AutoSize
Name Value
---- -----
SomePath two
Some three Environment: os: Windows
Pwsh: 7.4.6 |
While I can't comment on whether a new parameter makes sense or not this to me is less pressing as you can already achieve that with $envBlock = [Environment]::GetEnvironmentVariables()
$envBlock['NEW'] = 'foo'
Start-Process ... -Environment $envBlock
See the RFC as to why this is useful for direct invocations. It does make it cleaner to type so you don't have to reset the values back but the technical issue this RFC solves is the ability to do this in parallel invocations without stepping on each others toes. Take this for example 1..5 | ForEach-Object -Parallel {
$env:FOO = $_
bash -c 'echo $FOO'
$env:FOO = $null
} Your results will differ from mine but sometimes this works but the majority of the time this fails because
Whereas focusing on
There are many things that should be improved by |
Null chars are certainly a problem because env vars are simply a single string in some memory block of the process with each entry separated by The problem I am mentioning here specifically is if someone wanted to set an env var to an empty string or use an env var where the key was the same but in a different case. For example being able to set & @{ PAGER = '' } ... A practical example is As for duplicate env var keys it is more if you wanted to see both $envBlock = [Hashtable]::new()
$envBlock.FOO = 'hello'
$envBlock.Foo = 'world'
& $envBlock ... |
You've provided a workaround and shown the flaw yourself. Start-Process -AddEnvironment does not have this disadvantage. Everything else is not relevant to the discussion, as we are essentially only talking about "less typing" syntactic sugar. |
The
Most of these arguments effectively revolve around that fact you cannot integrate the process input/output into the PowerShell pipeline. I personally think any attempts to do so would just make it even more confusing as now we have 2 more parameter sets, having to complicate an already complicated cmdlet, and dealing with weird defaults where you need to opt into capturing the output rather than it just being done like the native command processor. I certainly would advocate a new cmdlet like
For a shell, being able to spawn sub processes is a critical component. This is even more important on non-Windows hosts where there are many tools out there that exist as a binary and not part of .NET. Speaking from my experience on the PowerShell Discord, this may not be the most common scenario I've heard but it is certainly a question I've seen around once a month. I don't think dismissing a common pattern and problem in PowerShell as syntactic sugar is really indicative of the need here. In any case this is an RFC so I do appreciate your comments, hopefully we can get more input from other people around the proposal. |
I'd really welcome this feature, although I'm not entirely sold on either proposed option:
Personally, I'd prefer having an The second question is what to do with pwsh cmdlets (as opposed to native commands). In an ideal world, we'd probably change the Personally, even without the provider changes, I'd still be inclined to support this for non-native commands in a kinda hackish way by setting the environment variables process-wide and then reverting the changes afterwards, and add a big disclaimer to the docs that you really shouldn't use this when using multiple runspaces inside a single process (which is still quite rare, so the chance for breakage seems acceptably low). |
For the record, that would help me easily solve PowerShell/PowerShell#20804. This would also be immensely helpful in testing and in executing code where we don't want to overwrite the environment variables for end users. |
@MatejKafka, thanks for your comments.
I definitely agree with this statement and am not 100% happy with the proposed solution but I ended up using it in the RFC because I found it was quite flexible in terms of:
The only saving grace IMO is that this would only work if used with the call operator. It does give a starting point for people to look for documentation by search
This is a nice idea but it does bring up a few concerns
I think having it be a statement that essentially acts like the call operator ( Maybe the end result is Windows users are out of luck and non-Windows users continue to use the
Using env vars scoped to a runspace would be interesting but I think the fact they are essentially backed by the process wide env block makes it too hard to achieve. This unfortunately is one of those things that would have had to happen in a v1/v2 release, doing so now would probably be too large of a change.
I think even with the disclaimer people will either still continue to ignore it and get surprised that it doesn't work well in multiple runspaces. I don't think that is quite rare now with Let's see what the WG thinks of this proposal, I definitely like the |
Adds the RFC to support specifying environment variable(s) that are only set on subprocesses. This is to support a feature that is currently preset on sh based shells like bash but is not possible in PowerShell without more verbose code or other limitations.