Conemu: Feature request: Auto update environment variables from system on WM_SETTINGCHANGE like explorer.exe

Created on 16 Dec 2015  路  31Comments  路  Source: Maximus5/ConEmu

When I change PATH or some other system environment variables, open a new tab in ConEmu, I think ConEmu should use the new system environment variables.
For explorer.exe, I open a new console by "open prompt here", it does use the new system environment variables.

settings type-enhancement

Most helpful comment

@norswap is correct.
As a user the expected behavior is to get the latest env variable when we open a new console.
The fact that it is a new window or a new tab not is not relevant, behavior should be consistent.
In tabbed mode I need to close all consoles and the window to be able to get my updates and this an annoying behavior.

Any update on the request?

Olivier

All 31 comments

Explorer ignores, well it actually do not even support, change/apply variables for its process.

But when you run ConEmu...

  1. It inherits all variables of parent process. For example, you run terminal from WAMP, GitExtensions, something, and you have properly changes/configured environment. Well, what would you have, if ConEmu just "reloads" variables from system? All "proper" variables would dissapear.
  2. User may even export changes from console up to ConEmu process. You would lose these changes too.

So, I consider processing of this message would be harmful

Hmm. Probably, ConEmu may ask user what they want to do, when WM_SETTINGCHANGE received.

I second this feature request.

ConEmu does not have to update all variables from the system. But for the PATH variable this functionality is a must.

Though because of the env variable export feature mentioned above (granted I understood its mechanism correctly) one will have to think carefully on how to make it right. To keep the internal changes to PATH variable intact you'll have to differentiate changes to the PATH variable introduced by the internal export feature from those introduced by the external changes to system and/or user PATH variables.

The idea I have in mind is a bit convoluted, but I'll try to explain it. When ConEmu starts you should save the original PATH variable that was inherited from the parent process to CONEMU_PATH.
Then with every change to the PATH variable by the internal _export_ feature you'll have to see what was added/removed to the original PATH and save those deltas. You should also apply those new changes (deltas) to CONEMU_PATH and then SetEnvironmentVariable on it to introduce those changes to the process.
Next whenever WM_SETTINGCHANGE message arrives that CONEMU_PATH should be completely overwritten by changes made to user or/and system PATH variables. Then accumulated internal changes should be applied to it and again SetEnvironmentVariable should be used used to apply those changes to the process.

Here is the pseudo-code for what was described above:

// Somewhere when the ConEmu process starts
GetEnvironmentVariable("PATH", &CONEMU_PATH, CONEMU_PATH.Length)

PathChangeDeltas internalPathChangeDeltas = new PathChangeDeltas();

...
switch (Msg.message)
{
...
    case WM_SETTINGCHANGE:
        CONEMU_PATH = MACHINE_PATH + ";" + USER_PATH;
        CONEMU_PATH = ApplyDeltas(CONEMU_PATH, internalPathChangeDeltas);
        SetEnvironmentVariable("PATH", CONEMU_PATH);
        break;
    case WM_INTERNAL_PATH_EXPORT:
        String EXPORTED_PATH = Msg.wParam;
        newDeltas = getPathChangeDeltas(CONEMU_PATH, EXPORTED_PATH);
        CONEMU_PATH = ApplyDeltas(CONEMU_PATH, newDeltas);
        internalPathChangeDeltas.Append(newDeltas);
        SetEnvironmentVariable("PATH", CONEMU_PATH);
        break;
...
}

MACHINE_PATH and USER_PATH will have to be pulled from the respective branches of Windows registry.

The Append() method, should you choose to actually implement something similar to what I described, can destroy mutually cancelling deltas, e.g. if one delta adds "C:\Windows" to the path and another one removes it then both those deltas can be safely removed.

@Maximus5, how does my suggestion of updating only the PATH variable contradict that note?

Also, I don't think that you will be able to easily change, if at all, Environment Variables of already started (in ConEmu) terminal processes (not sure what WAP and GitExtensions terminals are, I'm talking about things like cmd.exe, powershell.exe, or sh.exe started inside ConEmu). It is not the right thing to do anyway.

But timely update of the PATH variable of the ConEmu process so that all newly started terminals inherit the updated PATH shouldn't be a problem. At least that is the default behaviour I would expect of ConEmu.

I think explorer.exe update environment variables of itself from the following registry entries on WM_SETTINGCHANGE:

HKEY_CURRENT_USER\Environment
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment

Then explorer.exe start a new process, the new process inherit the new environment variables.
ConEmu may provide an option to take this behavior.
For simplicity, we can ignore the exported changes from console up to ConEmu process.
Otherwise, there should be an algorithm to calculate the delta from ConEmu startup environment variables to system environemnt variables. And on WM_SETTINGCHANGE, load new system environemnt variables and apply the delta.

@strrchr you are correct about registry entries.

If you ignore the exported changes from console up to ConEmu process then, well, you will just break that exporting functionality. My suggestion, if implemented, would combine both features.

Though I already see that the algorithm I described above is not exactly correct. To calculate correct deltas you'll have to check for differences between PATH that was just exported up from terminal process and the original PATH the terminal process was started with. That is in ConEmu you'll have to store a per terminal process PATH snapshot (taken when that terminal process was started) for the purpose of calculating deltas.

On the side note, @Maximus5, consider the following case. You have two different terminals running in ConEmu. Let's say that ConEmu's PATH is "A;B;C". When two terminals were created they inherited that PATH. Now the first terminal makes changes to the PATH variable "A;B;C" -> "K;L;M". And it exports that path up to the ConEmu. Now ConEmu's PATH is "K;L;M". Then the second terminal changes its PATH "A;B;C" -> "X;Y;Z" and exports it up to ConEmu. Boom, you've just overwritten the "proper" PATH that was exported up by the first terminal with "proper" PATH that was exported up by the second terminal.

In the above case you allow one terminal to overwrite changes that were made by the other terminal, but at the same time you don't like the idea of overwriting ConEmu's environment by the system-wide environment changes, which, I argue, should at least take precedence to bottom-up environment updates.

PATH may be set not only by "export".
As I've said before, ConEmu may be used as a terminal for other products (WAMP (Open Server), MAME, build environments like Mozilla, and so on).
All of them set env.vars, and PATH is one of them.

So, PATH actually differs from system at the moment ConEmu starts.

However, we may save this startup delta too.

I use _ConEmu_ as a replacement for cmd, so I want to be able to use my newly added or modified environment variables in new tabs of _ConEmu_, but it will totally ignore this changes for new tabs for reasons that you mentioned above.

Can't _ConEmu_ just have an option for this(auto processing of WM_SETTINGCHANGED) or at least have a menu button or a command that reload all settings? This way new tabs may work with new settings and existing tabs can continue with old copy of variables.

+1

so...there are no way to refresh the environment variables of specific tab other than relogin?

@zhaoguoyuan Look, even if ConEmu would renew its environment (in roadmap actually) the application, running in ConEmu tab is running on their own responsibility. There is no proper way to "change" environment in some external process. For example, cygwin doesn't ever call Windows environment API functions.

@Maximus5 I think I understood what you said, I totally agree with that. Obviously there are no perfect on punch solution for all the problems, since "environment variables" is a big topic, especially when ConEmu interact with OS or other software in two ways, maybe we can list up the use cases and try to discuss them separately.

+1 for this feature. I appreciate that ConEmu can do many wonderful things (export variables, host WAMP and what not) and one day maybe I'll learn to appreciate this too. But for the very simple (and probably the most common) use-case, when ConEmu acts as a multi-tab cmd.exe, it would be nice to minimise the surprise for the user.

As said by someone above:

  • if I start a new cmd.exe Window, I get a snapshot of the current system environment variables
  • in Console2, if I open a new tab, I get a snapshot too

Users come to ConEmu from these less fancy tools and have learned to get around with this not-very-fancy behaviour. Hardly anyone will be able to appreciate the fanciness as something positive...

@Maximus5

The problem is that the behaviour is inconsistent when consoles are set up to open in new tabs.
(And I think this is what @sferencik is really trying to say.)

  • The first time I launch a console, ConEmu launches and inherits the explorer's environment.
  • The second time I launch it, assuming a ConEmu window is open, I get a new tab in that window, which inherits the ConEmu window's environment (so any intermediate changes to the explorer environment are not picked up).

In one case I inherit the explorer's environment, in the other I do not. Confusing, and bad.

If you set up ConEmu to open new windows instead of new tabs, you don't have that problem. Another inconsistency!

I don't really care about processing WM_SETTINGCHANGE or not. The environment of the ConEmu window doesn't preoccupy me*. It's the console I launched that really needs to inherit the explorer's environment

* Although I'm all in favor of https://github.com/Maximus5/ConEmu/issues/987 -- but at least the current behaviour has a certain logic to it.

+1 for this feature
I would really love if I could on demand reload env variables in current tab and/or all tabs.

@norswap is correct.
As a user the expected behavior is to get the latest env variable when we open a new console.
The fact that it is a new window or a new tab not is not relevant, behavior should be consistent.
In tabbed mode I need to close all consoles and the window to be able to get my updates and this an annoying behavior.

Any update on the request?

Olivier

+1 for this feature, at least as a menu option to manually reload environment. Sometimes it's a problem to restart whole ConEmu, e.g. due to long-running process in one of the tabs.

Fortunatelly, there's a workaround: Start the new shell (cmd.exe) from explorer and then use ConEmu's function "Attach to..." to move it into ConEmu.

+1. Very annoying when you have multiple consoles open and have to close all.

Sort of workaround.
You may run cmd (or cmd -new_console:z if you use DefTerm) and export variables to ConEmu. Perhaps attach is required before export.
I believe, this may be automated via one shortcut on the Desktop.

Call me crazy but its been 3 years, this is basic. Literally I only use Windows because my stupid company is bound to it but I swear never to code again supporting windows in whatever open source projects I contribute...

Seems like chocolatey has already resolved this issue with a script:

https://github.com/chocolatey/choco/blob/master/src/chocolatey.resources/redirects/RefreshEnv.cmd

I have been using it along with setx command and manual modifications and has been working like a charm so far.

The only "but" I have is that it only works in CMD, so if someone is using cygwin or some other shell derivative then you need to close it, "refresh" CMD and open again.

The ability to run a script when opening a new tab would indeed be of tremendous help. I don't remember very well (it's been more than 18 months) but I tried to investigate that and I don't think it is possible in ConEmu. The ability to run a script whenever a console is opened (no matter the method) would also help. I someone wants to investigate...

@norswap
It should be possible to run a script when opening a new tab. There is also a default script ConEmu adds to CMD tabs.
If you look into Settings -> Startup -> Tasks and click on one of the CMD tasks you should see its command in a text field. Usually it should start with cmd.exe. What you see after the /k option is a script that is run when the tab is opened. For example I use this:

cmd.exe /k "%ConEmuBaseDir%\CmdInit.cmd" -git C:\Development\Tools\ConEmuCmdInit.cmd''

%ConEmuBaseDir%\CmdInit.cmd is the ConEmu default script that does adjustments to the prompt and adds Git information if the -git option is specified. Followed by my own ConEmuCmdInit.cmd script that does initialization of my development environment.

Indeed, I thought I had tested that already, but apparently not. I set my init script up to call a script that resets the PATH variable (one could use the ResetEnv.cmd script @Koriit linked above) and it works fine :+1:

In my first 5 minutes of using ConEmu, after several years of using several other terminals on Windows, I ran smack into this issue.

I really can't understand that. Do you change environment variables every 5 minutes on system level?

>scoop install yarn
...
>yarn
bash: yarn: command not found

My first instinct was to open a new terminal, which didn't work. I then had to kill every terminal before it took effect, which I assumed was a bug.

@Maximus5 No, but happens frequently that you have some consoles open, you need to install something (changes PATH), then you'd expect that opening a new console tab would have the new path (as it does when you open it from explorer). But nay. So now you either have to launch a new instance of ConEmu (but only if you didn't configure it to be single instance IIRC). Or remember the flag for launching a separate instance (no one does). Or (what people actually do) - clause all open consoles and relaunch.

Given how incredibly common that scenario is, and given how many options ConEmu already has, would it really be the end to fetch the new environment variable values from the register when launching a new console? Or potentially add the option to control this behaviour?

Agree with feature requesters. As many people i also work on different solutions every week and have to install various tools, etc to try them out. Generally i have at least 5-6 consoles open with useful command histories. It really is an incovenience to restart cmder every time i install something because it doesn't have the refreshed PATH.

2019-05-27_02-00-25

When ConEmu receives the WM_SETTINGCHANGE with lParam=Environment it tries to load environment from registry, compare the data with previous try (from startup or WM_SETTINGCHANGE) and applies changes into it's own environment.
New variables will be available in the new consoles.
If one want to apply new variables to some active console, ConEmuC -GuiMacro EnvList prints actual NAME=VALUE pairs, you may parse them and apply into your shell.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rfgamaral picture rfgamaral  路  3Comments

altbdoor picture altbdoor  路  4Comments

phazei picture phazei  路  6Comments

imalos picture imalos  路  5Comments

pyhedgehog picture pyhedgehog  路  3Comments