-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Environment.SetEnvironmentVariable does not support setting empty values #50554
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
We could start with: namespace System
{
public static partial class Environment
{
public static void SetEnvironmentVariable(string variable, string? value, bool AllowEmptyValue = false)
public static void SetEnvironmentVariable(string variable, string? value, EnvironmentVariableTarget target, bool AllowEmptyValue = false)
}
} |
I think that it would be better to just fix the API to do the right thing by default. It is a pretty minor breaking change, not worth it to introduce a new API for it. |
@danmoseley closed #15660 with "This would be too breaking to change now, I think." :-) This API is so popular that it can break a lot. Thinkin g about PowerShell I'm even afraid to imagine how many scripts will break. I checked PowerShell follows the .Net behavior (and cmd.exe too). |
We are only talking about null vs. empty string distinction. I expect that it should be very rare for this distinction to matter. I would love to see real-world code examples that this change breaks. |
Before the breaking change we could introduce an analyzer to suggest users to use null instead of empty string for removing environment variable. And add the recommendation in docs. |
I went through the @stephentoub list. I found one place that would be broken, the rest is fine or probably fine. Ok: https://devdiv.visualstudio.com/DevDiv/_git/VS?path=%2Fsrc%2Fdebugger%2Fsymbollocator%2Fsymbollocator.cpp&_a=contents&version=GBmain (internal link) Ok (PATH) ? (probably ok) Ok:
? (probably ok) |
But then you'd have to ask how many of these "places" assign an empty string, but check for null. The affected pool seems really tiny. |
Some, sure. Others do things like: static readonly bool s_blahEnabled = Environment.GetEnvironmentVariable("blah") != null; |
Also worth noting that there is currently no P/Invoke workaround on Unix-like platforms, because environment modifications made by native libraries aren't seen by managed callers (and vice versa; see #9529 for background). It is on Unix that the practice of setting empty-value environment variables is common: in some use cases, environment variables serve as flags based on their existence alone, in which case their value is irrelevant. POSIX-compatible shells make setting "value-less" (de facto value: the empty string) easy: # Create 'NO_VALUE_ without a value (with the empty string as the value).
export NO_VALUE=
# Child process-scoped equivalent
NO_VALUE= foo -bar Due to the current inability to set such variables in .NET, PowerShell too lacks this ability. With individual variables set deliberately that isn't much of a problem - just use something like # Run from bash, for instance:
NO_VALUE= pwsh -noprofile -c - <<'EOF'
"NO_VALUE exists? " + ('' -eq [Environment]::GetEnvironmentVariable('NO_VALUE'))
# Save the current value
$saved = $env:NO_VALUE
# ... temporarily modify the value
# Try to restore the previous value.
# !! With a value-less variable, this REMOVES it.
$env:NO_VALUE = $aved
# !! This now reports $false
"NO_VALUE exists? " + ('' -eq [Environment]::GetEnvironmentVariable('NO_VALUE'))
EOF |
Description
Environment.SetEnvironmentVariable
internally normalizes thevalue
argument from empty string tonull
:runtime/src/libraries/System.Private.CoreLib/src/System/Environment.cs
Lines 233 to 237 in 4523fbf
This is preventing the callers of this API to set variables to an empty value, which is otherwise supported on all platforms.
Consider the following code on Windows:
It prints
True False
as the P/Invoke works as expected and the BCL call deletes the variable, same as ifEnvironment.SetEnvironmentVariable("_MYVAR", null)
was called.This program is expected to print
True True
.Configuration
.NET Core 5.0.201 on Windows 10
Regression?
Not a regression, this behavior was inherited from .NET Framework.
Other information
I am proposing to make a breaking change to the API and remove the
""
->null
normalization. If this is not possible, please consider adding a new API that would allow the program to set environment variables to empty values.Note that
ProcessStartupInfo.EnvironmentVariables
supports empty values and has actually the opposite problem of interpretingnull
as""
(#34446).This issue was found when moving an out-of-proc invocation of a tool to in-process and trying to keep the same logic of passing environment variables (previously via
ProcessStartupInfo
) to the current process withEnvironment
.The text was updated successfully, but these errors were encountered: