[BUG] Programs launched from SystemTrayMenu don't get updated system settings (like PATH)
Hello, First, thank you for creating such a useful tool. I use it every day and find it invaluable. I've encountered a minor issue where SystemTrayMenu does not seem to recognize changes to system environment variables while it is running.
For example, if I install a new application that modifies the system's PATH variable, any new Command Prompt instance launched from SystemTrayMenu will not inherit the updated PATH. It continues to use the environment variables that were present when SystemTrayMenu was first started.
The only workaround is to completely exit and restart SystemTrayMenu , which is inconvenient for an application designed to run continuously in the system tray.
Steps to Reproduce
- Start SystemTrayMenu .
- Create a button to launch the Windows Command Prompt (cmd.exe).
- Modify a system environment variable. For example, add a new directory (e.g., C:\MyTestFolder) to the system PATH.
- Click the Command Prompt button in SystemTrayMenu to launch a new terminal.
- In the new command prompt window, type path and press Enter. Actual Result: The output of the path command does not include the newly added directory (C:\MyTestFolder).
Expected Result: The output of the path command should include the new directory, reflecting the current system settings, just as it would if launched from the Windows Start Menu.
Suggested Behavior Ideally, SystemTrayMenu would automatically (or optionally) detect system setting changes. When a program is launched from a SystemTrayMenu button, it should always inherit the most current system environment variables without requiring a restart of the application.
Thank you for your time and for this great application.
Hello @BigBauf
First, thank you for the detailed feedback! It really helped clarify the behavior.
The issue happens because SystemTrayMenu reads the environment variables once at startup from its parent process (usually Explorer). When system or user environment variables (like PATH) are changed, Windows writes the new values to the registry and broadcasts a WM_SETTINGCHANGE message. However, SystemTrayMenu currently does not handle this message, so any new processes it launches (e.g., CMD) inherit the old environment. This is why restarting SystemTrayMenu is needed to pick up changes.
Solution: Listen for WM_SETTINGCHANGE and refresh environment
Add a message handler in the main window or tray application:
protected override void WndProc(ref Message m) { const int WM_SETTINGCHANGE = 0x001A; base.WndProc(ref m);
if (m.Msg == WM_SETTINGCHANGE)
{
string param = m.LParam != IntPtr.Zero ? Marshal.PtrToStringAuto(m.LParam) : string.Empty;
if (param == "Environment")
{
// Environment variables changed
RefreshEnvironmentVariables();
}
}
}
Refresh environment variables by reading the current system and user values from the registry:
private void RefreshEnvironmentVariables() { var sysEnv = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment"); var userEnv = Registry.CurrentUser.OpenSubKey(@"Environment");
var newEnv = new Dictionary<string, string>();
foreach (var name in sysEnv.GetValueNames())
newEnv[name] = sysEnv.GetValue(name)?.ToString();
foreach (var name in userEnv.GetValueNames())
newEnv[name] = userEnv.GetValue(name)?.ToString();
// Store updated environment for new processes
this.CurrentEnvironment = newEnv;
}
Launch new processes with the updated environment:
var startInfo = new ProcessStartInfo("cmd.exe") { UseShellExecute = false, };
foreach (var kvp in CurrentEnvironment) { startInfo.Environment[kvp.Key] = kvp.Value; }
Process.Start(startInfo);
We need ti omplement this in the futire
Workaround
If you want a solution now, a simple workaround is to use a wrapper script to always load the latest environment from the registry before starting CMD:
@echo off for /f "tokens=1,2*" %%A in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"') do set "%%A=%%C" for /f "tokens=1,2*" %%A in ('reg query "HKCU\Environment"') do set "%%A=%%C" start cmd.exe
SystemTrayMenu can launch this script instead of CMD directly.
CMD will always start with the current system and user environment variables, without restarting SystemTrayMenu.
This approach ensures new processes always inherit the most up-to-date environment.
I’m not sure how userEnv is populated, but based on this code, the PATH value from userEnv will overwrite the one from sysEnv. Since PATH is usually a combination of system and user entries, this behavior should ideally merge the values instead of replacing them.
Just as an idea, not sure if this is beneficial: Maybe just relaunch the application in case of environment changes?