Skip to content

Support environment variables in the settings#15082

Merged
DHowett merged 26 commits intomicrosoft:mainfrom
ianjoneill:feature/2785-profile-env-vars-with-string-map
Apr 11, 2023
Merged

Support environment variables in the settings#15082
DHowett merged 26 commits intomicrosoft:mainfrom
ianjoneill:feature/2785-profile-env-vars-with-string-map

Conversation

@ianjoneill
Copy link
Contributor

@ianjoneill ianjoneill commented Apr 1, 2023

Existing environment variables can be referenced by enclosing the name in percent characters (e.g. %PATH%).

Resurrects #9287 by @christapley.

Tests added and manually tested.

Closes #2785
Closes #9233

Co-authored-by: Chris Tapley [email protected]

@microsoft-github-policy-service microsoft-github-policy-service bot added Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Area-Settings Issues related to settings and customizability, for console or terminal Area-TerminalConnection Issues pertaining to the terminal<->backend connection interface Product-Terminal The new Windows Terminal. labels Apr 1, 2023
@zadjii-msft
Copy link
Member

holy shit the madman actually did it

@ianjoneill
Copy link
Contributor Author

Test failures are CI flakes

image

@zadjii-msft
Copy link
Member

idle thought before reading the code: the original PR might predate layering. Lets see how this works with layering. Can the defaults say (for example) TERM=windows-terminal, and then a profile say TERM=, to unset it? Or does setting it in a profile entirely replace the lower layer? If it's a per-variable layering, we could use that to vaguely do #11057.

@ianjoneill
Copy link
Contributor Author

Currently the concrete profile's environment completely replaces the one specified in defaults.

So if you've got:

"defaults": {
  "environment": {
    "Foo": "Bar"
  }
},
"list": [
  {
    "name": "PowerShell",
    "environment": {
      "Baz": "Qux"
    }
  }
]

Your PowerShell profile will get Baz=Qux and your cmd profile will get Foo=Bar.

@zadjii-msft zadjii-msft added the Needs-Discussion Something that requires a team discussion before we can proceed label Apr 3, 2023
@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Apr 4, 2023
Copy link
Contributor Author

@ianjoneill ianjoneill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some thoughts before I open Visual Studio

Comment on lines 86 to 95
til::env environment;
auto zeroEnvMap = wil::scope_exit([&]() noexcept {
// Can't zero the keys, but at least we can zero the values.
for (auto& [name, value] : environment)
for (auto& [name, value] : environment.as_map())
{
::SecureZeroMemory(value.data(), value.size() * sizeof(decltype(value.begin())::value_type));
}

environment.clear();
environment.as_map().clear();
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm missing something, if we did this as part of regenerate() the map would be cleared on exit of the method which would mean the map would be populated and immediately cleared.

It would probably make sense to extract this for loop into a clear() method on til::env, so that the caller doesn't need to worry about the internal representation.

With regards to whether it's necessary, I can't answer that - I don't know why the code originally did this. It's possible the environment could contain sensitive information (e.g. temporary credentials), which you may want to clear out.

}
_reloadEnvironmentVariables = winrt::unbox_value_or<bool>(settings.TryLookup(L"reloadEnvironmentVariables").try_as<Windows::Foundation::IPropertyValue>(),
_reloadEnvironmentVariables);
_profileGuid = winrt::unbox_value_or<winrt::guid>(settings.TryLookup(L"profileGuid").try_as<Windows::Foundation::IPropertyValue>(), _profileGuid);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah - it seemed silly both this and TerminalPage doing the same dance fiddling with WSLENV though.

@microsoft-github-policy-service microsoft-github-policy-service bot removed the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Apr 4, 2023
@zadjii-msft zadjii-msft added this to the Terminal v1.18 milestone Apr 4, 2023
@zadjii-msft zadjii-msft self-assigned this Apr 6, 2023
@ianjoneill
Copy link
Contributor Author

Just FYI I should be able to take a look at this tomorrow (Friday).

@DHowett
Copy link
Member

DHowett commented Apr 7, 2023

This is very subtle (and I am only testing as of >5 hours ago, so please ignore if changed), but you can resurrect inherited environment variables depending on sort order.

I don't know if I think this is an issue worth fixing, but it is fun!

"environment": {
    "Z_NEW_PATH": "%PATH%", // gets new path!
    "PATH": "A",
    "0_OLD_PATH": "%PATH%", // gets old path!
}

@ianjoneill
Copy link
Contributor Author

This is seemingly how Windows resolves environment variables - though the order as far as I can tell is the order they're inserted into the registry.

Starting off with a system environment variable FOO=Foo and setting up the registry with REG_EXPAND_SZ user variables 0_FOO=%FOO%, FOO=NewFoo and Z_FOO=%FOO%, as below:
image

Leads to them being resolved as 0_FOO=Foo, FOO=NewFoo and Z_FOO=NewFoo in a conhost window, as below:
image

Worth pointing out though that if you create the FOO user variable in the system properties window, it's set up as a REG_SZ variable - so it does get resolved first, leading to 0_FOO and Z_FOO both resolving to NewFoo.

I guess we could put in a pre-processing step that inserts variables with values not containing percent characters into the environment map first. It would require iterating over the values in the map twice though and would complicate the logic somewhat - your call.

@DHowett
Copy link
Member

DHowett commented Apr 7, 2023

Oh, no, I'm totally happy with how it works today! I legitimately found it interesting 😄

@zadjii-msft zadjii-msft removed the Needs-Discussion Something that requires a team discussion before we can proceed label Apr 11, 2023
@zadjii-msft zadjii-msft removed their assignment Apr 11, 2023
Copy link
Member

@DHowett DHowett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love it. Thanks @ianjoneill and @christapley :)

@eggbean
Copy link

eggbean commented Oct 10, 2024

So glad to find that it's possible to use variables in settings.json but it doesn't seem to work with boolean settings which expect a true/false value.

image

😞

@DHowett
Copy link
Member

DHowett commented Oct 10, 2024

So glad to find that it's possible to use variables in settings.json

Just to clarify: as of this PR, it is possible to set environment variables in settings.json for the spawned process to inherit. It is not generally possible to use environment variables in settings.json :)

@eggbean
Copy link

eggbean commented Oct 10, 2024

@DHowett Oh, that sucks. Just when I thought that I had finally found a way to easily manage my settings.json in git. Thanks for the info.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Settings Issues related to settings and customizability, for console or terminal Area-TerminalConnection Issues pertaining to the terminal<->backend connection interface Issue-Bug It either shouldn't be doing this or needs an investigation. Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Priority-3 A description (P3) Product-Terminal The new Windows Terminal.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Order of environment variables different in WT (Feature Request) Terminal Environment setting (like in VScode)

5 participants