-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Provide simple one-time setting of environment variable #3316
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
Comments
This would be a great usability enhancement. A lot of our tests rely on the current cumbersome method because of the lack of this feature. |
It's easier to implement this as an argument to Start-Process main.exe -Environment @{ FOO = 'bar' } The source code is in PowerShell/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs Lines 1574 to 1579 in 0cc1f06
This syntax also reminds user that starting a new process in Windows is more expensive (it took me a second to start a new PowerShell). The idea is provided by #4671. |
|
Just yesterday I came up with a proof of concept by abusing the CommandNotFoundHandler. |
@johnjelinek: Adding an Even though Aside from being more verbose, Love the idea; just to spell it out: it should work for multiple env. variables too, as in POSIX-like shells: # In a POSIX-like shell such as Bash
$ foo=1 bar=2 sh -c 'echo $foo $bar' # -> '1 2' Presumed PS equivalent: PS> $env:foo=1 $env:bar=2 sh -c 'echo $foo $bar' # -> '1 2' Given that this a feature for child processes (external programs), in the context of which only environment variables can be meaningfully defined, perhaps even omitting the # Implied `env:`?
PS> $foo=1 $bar=2 sh -c 'echo $foo $bar' # -> '1 2' Given that these variables are by definition command-scoped - only the target process sees them - I think that should be fine. |
Hmm. That would be nice, but I feel like the syntax is a bit obtuse. I'd suggest perhaps something like this? with @{PATH = $NewPath; JEKYLL_ENV = $jekyll} & $command $params That would allow use of multiline syntax quite naturally for less lengthy lines and better readability: with @{
PATH = $NewPath
JEKYLL_ENV = $jekyll
} & $command $params It also has a direct tie-in to the existing EDIT: maybe |
The hashtable syntax isn't horrible - that's what I ended up with here - invoked like: Invoke-WithEnvironment @{ JEKYLL_ENV="production" } { jekyll build } |
Would it make sense to simply add a |
Adding |
I suggest to discuss the parameters in #4671. |
However, at least to me, this proposal is about a syntax that is:
@vexx32's proposal definitely meets (b); with respect to (a): while definitely more PowerShell-like, it still feels a bit verbose, especially for the - presumably common - case of defining a single env. var. If, by contrast, we go all in, we could simply mimic POSIX syntax as-is: PS> foo=1 bar=2 sh -c 'echo $foo $bar' # -> '1 2' While a tad obscure, you could argue that we're entering a different world here anyway - that of external programs - where different rules already apply (such as |
The obscure syntax creates a discovery problem. Interactive, you can use a more terse syntax: icm -env @{ foo=1; bar=2 } sh -c 'echo $foo $bar' |
Given there is also an issue with PS effectively ignoring a native app's exit code, maybe this could be combined into a command like When invoking native apps you often want this "throw on non-zero exit code" functionality. I can't tell you how many times I've helped folks figure out why their build was passing when the log shows obvious errors. |
Eh, I mean... that's kinda just duplicating what Start-Process could do with an extra parameter or two. I'm not sure how much sense it makes to have two commands in that space at the moment? 🤔 |
|
You could easily enhance Start-Process to accept a parameter (switch? int[]?) to throw on any non-zero or a predefined list of "bad" exit codes, though; that doesn't really mandate an entirely new command, I would think. |
Note that foo -bar || exit 1
# or
foo -bar || throw Unfortunately, that currently doesn't actually work, because you're required to wrap the foo -bar || $(throw) The ship hasn't sailed yet, fortunately, so I invite you to join the conversation at #10967. Update: Oops! Missed the fact that this was already reviewed and decided against; still, I'm hopeful that this will be reconsidered. |
I think it would be beneficial to provide something that is robustly terse, and doesn't rely on aliases (or costly cmdlet calls, for that matter).
That could be remedied with a dedicated conceptual help topic covering invocation of native apps, which is definitely urgently needed even for the current capabilities - see MicrosoftDocs/PowerShell-Docs#5152 |
I don't think the addition to Invoke-Command (or Start-Process) is mutually exclusive to something terse. If we wanted to explore that route, my preference is to use Bash syntax exactly so user would be able to cut and paste most examples (barring other issues we have with arg parsing/passing...) and have them just work in PowerShell. |
I agree that this would be best; to recap what that looks like: # Define command-scoped (child-process-only) $env:foo and $env:bar env. variables
foo=1 bar=2 sh -c 'echo $foo $bar' # -> '1 2'
Agreed, and #4671 already proposes that for With I think it makes sense to always restrict the specified environment variables to child processes, which means that the current process' environment is not modified - that's how it (sensibly) works in POSIX-like shells. Therefore, in the following invocation the Powershell code inside the # $env:foo is NOT defined in the script block.
Invoke-Command -Environment @{ foo = 'bar' } -ScriptBlock { "`$env:foo is: $env:foo" } In short: I think it's sufficient to offer the Bash-like syntax specifically for external programs and otherwise enhance |
A real life example where they use this concept in bash: https://www.twilio.com/blog/2017/08/working-with-environment-variables-in-node-js.html
|
First step was done in #10830. |
This is a feature request, not a bug report, I don't think it can really become stale. |
Not just a feature request, but a reasonably high "upvoted" feature request. |
Good fucking job, bot |
I keep running across documentation (from Microsoft BTW), that assumes this syntax will just work. ![]() |
I think it would be more useful for |
|
Personally I don't mind a bit of ceremony. I'll take readability over obscure terseness any day of the week. |
I'd prefer something quick to bang out on the command line and easy to remember without much fanfare. If I only had intentions of using the feature in scripts then I wouldn't much care how verbose it was. |
Was thinking about converting some bash scripts to PowerShell to improve their readability, but running a typical make command without that requires a lot of boilerplate. What is the status and/or consensus on this one - will it come to PowerShell? |
If there are no technical limitations or syntax conflicts I would really vote for making bash-like syntax just work in Powershell. In my experience most of the shell examples in any documentation are in (ba)sh, sometimes even on Microsoft docs. Luckily 80% of the time these examples works in Powershell just fine, 19% of other examples doesn't work because:
I would be great to decrease these chances of having to manually edit a command that you've copied, just because you use less popular shell. It would be a huge usability win for new and long-time users of Powershell. |
Afaict, one of the blocking issues is that environment variables are global for the whole process, and PowerShell now supports thread jobs, meaning that there may be multiple commands running at once inside a single process – if you set an environment variable in multiple thread jobs, it will cause conflict, and re-architecting PowerShell to have separate env vars for each job would be quite hard. However, I agree that even with this caveat, it would be worth it to add some form of support for this, since most users do not use thread jobs, and for native commands, the implementation may avoid the issue alltogether. Above, I proposed to use a fish-style env TEST=1 cmd /c 'echo TEST=%TEST%' This syntax is not compatible with Bash, but you only need to prefix the expression with Proof of concept: https://github.com/MatejKafka/powershell-profile/blob/master/CustomModules/ScopedEnvironment/ScopedEnvironment.psm1 |
In summary:
|
I think going with Unix syntax
I would recommend instead implementing a |
Number 4. is a non-issue, given that, e.g. Numbers 1. - 3. are fair points, but: There are two major drivers for this feature:
Ensuring the latter is what makes the inconsistencies you mention unavoidable, just like we've already introduced other inconsistencies for the sake of compatibility with POSIX shells (automatic globbing (wildcard expansion) and tilde ( As for the It occurred to me that implementing Thus, there are only two options:
Neither option is great:
|
7+ years and this is still impossible. pwsh is not a shell replacement without this basic feature. Why not even an Environment flag? |
I have been looking into implementing vim-test/vim-test#832 and it would actually be nice to have some shell-agnostic syntax. For now it's |
Instructions for many tools from the Linux world suggest setting an environment variable for a single invocation of a command like:
The equivalent in PowerShell is cumbersome:
I believe a similar syntax could work in PowerShell:
The text was updated successfully, but these errors were encountered: