Skip to content

Commit

Permalink
gh-468: Auto update environment variables, apply them to new consoles.
Browse files Browse the repository at this point in the history
  • Loading branch information
Maximus5 committed May 26, 2019
1 parent 0fc185f commit b295dca
Show file tree
Hide file tree
Showing 13 changed files with 253 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/ConEmu.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@
<ClInclude Include="ConEmu\ShObjIdl_Part.h" />
<ClInclude Include="ConEmu\SizeInfo.h" />
<ClInclude Include="ConEmu\Status.h" />
<ClInclude Include="ConEmu\SystemEnvironment.h" />
<ClInclude Include="ConEmu\TabBar.h" />
<ClInclude Include="ConEmu\TabCtrlBase.h" />
<ClInclude Include="ConEmu\TabCtrlWin.h" />
Expand Down Expand Up @@ -637,6 +638,7 @@
<ClCompile Include="ConEmu\SetPgViews.cpp" />
<ClCompile Include="ConEmu\SizeInfo.cpp" />
<ClCompile Include="ConEmu\Status.cpp" />
<ClCompile Include="ConEmu\SystemEnvironment.cpp" />
<ClCompile Include="ConEmu\TabBar.cpp" />
<ClCompile Include="ConEmu\TabCtrlBase.cpp" />
<ClCompile Include="ConEmu\TabCtrlWin.cpp" />
Expand Down
6 changes: 6 additions & 0 deletions src/ConEmu.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,9 @@
<ClInclude Include="ConEmu\Status.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="ConEmu\SystemEnvironment.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="ConEmu\TabBar.h">
<Filter>Headers</Filter>
</ClInclude>
Expand Down Expand Up @@ -1076,6 +1079,9 @@
<ClCompile Include="ConEmu\Status.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="ConEmu\SystemEnvironment.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="ConEmu\TabBar.cpp">
<Filter>Sources</Filter>
</ClCompile>
Expand Down
74 changes: 74 additions & 0 deletions src/ConEmu/ConEmu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SetPgDebug.h"
#include "SetPgInfo.h"
#include "Status.h"
#include "SystemEnvironment.h"
#include "TabBar.h"
#include "TrayIcon.h"
#include "Update.h"
Expand Down Expand Up @@ -131,6 +132,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define DEBUGSTRDPI(s) DEBUGSTR(s)
#define DEBUGSTRNOLOG(s) //DEBUGSTR(s)
#define DEBUGSTRDESTROY(s) DEBUGSTR(s)
#define DEBUGSTRSETCHANGE(s) DEBUGSTR(s)
#ifdef _DEBUG
//#define DEBUGSHOWFOCUS(s) DEBUGSTR(s)
#endif
Expand Down Expand Up @@ -386,6 +388,8 @@ CConEmuMain::CConEmuMain()
}
}

saved_environment_ = std::make_shared<SystemEnvironment>();
saved_environment_->LoadFromRegistry();

// Load current comspec form registry
HKEY hk;
Expand Down Expand Up @@ -8239,6 +8243,58 @@ void CConEmuMain::RefreshWindowStyles()
//OnTransparent();
}

void CConEmuMain::ReloadEnvironmentVariables()
{
const wchar_t dbg_msg[] = L"Reloading environment variables from system registry";
if (!LogString(dbg_msg)) DEBUGSTRSETCHANGE(dbg_msg);


auto new_environment = std::make_shared<SystemEnvironment>();
new_environment->LoadFromRegistry();

const auto& old_data = saved_environment_->env_data;
const auto& new_data = new_environment->env_data;
for (const auto& old_var : old_data)
{
if (!new_data.count(old_var.first))
{
std::wstring dbg_log(L" Erased: `" + old_var.second.name
+ L"`, old value: `" + old_var.second.data + L"`");
if (!LogString(dbg_log.c_str())) DEBUGSTRSETCHANGE(dbg_log.c_str());

SetEnvironmentVariable(old_var.second.name.c_str(), nullptr);
}
}
for (const auto& new_var : new_data)
{
auto old_iter = old_data.find(new_var.first);
if (old_iter == old_data.end()
|| (old_iter->second.data != new_var.second.data))
{
std::wstring old_value((old_iter == old_data.end())
? std::wstring(L"Absent")
: std::wstring(L"`" + old_iter->second.data + L"`"));
std::wstring dbg_log(L" Changed: `" + new_var.second.name
+ L"`, new value: `" + new_var.second.data + L"`, old_value: "
+ old_value);
if (!LogString(dbg_log.c_str())) DEBUGSTRSETCHANGE(dbg_log.c_str());

if (new_var.second.expandable)
{
CEStr value(ExpandEnvStr(new_var.second.data.c_str()));
if (!value.IsEmpty())
{
SetEnvironmentVariable(new_var.second.name.c_str(), value);
continue;
}
}
SetEnvironmentVariable(new_var.second.name.c_str(), new_var.second.data.c_str());
}
}

saved_environment_ = new_environment;
}

void CConEmuMain::OnGlobalSettingsChanged()
{
UpdateGuiInfoMapping();
Expand Down Expand Up @@ -13693,6 +13749,18 @@ LRESULT CConEmuMain::WndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam

case WM_SETTINGCHANGE:
{
const wchar_t* change_verb = nullptr;
const wchar_t kEnvironmentVerb[] = L"Environment";
wchar_t szDbg[128]; swprintf_c(szDbg, L"WM_SETTINGCHANGE: W=x%04X, L=x%04X", (DWORD)wParam, (DWORD)lParam);
if (lParam && !IsBadStringPtr((LPCWSTR)lParam, 64))
{
change_verb = (LPCWSTR)lParam;
wcscat_c(szDbg, L", ");
size_t cur_len = wcslen(szDbg);
lstrcpyn(szDbg + cur_len, change_verb, std::size(szDbg) - cur_len);
}
if (!LogString(szDbg)) DEBUGSTRSETCHANGE(szDbg);

if (wParam == SPI_SETWORKAREA)
{
ReloadMonitorInfo();
Expand All @@ -13704,6 +13772,12 @@ LRESULT CConEmuMain::WndProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam
if (wm != wmNormal && !isIconic() && isMeForeground())
SetWindowMode(wm);
}

if (change_verb && 0 == wcscmp(change_verb, kEnvironmentVerb)
&& gpSet->AutoReloadEnvironment)
{
ReloadEnvironmentVariables();
}
} break;

case WM_DISPLAYCHANGE:
Expand Down
7 changes: 7 additions & 0 deletions src/ConEmu/ConEmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ union CESize;
class CPushInfo;
class CAltNumpad;
struct HandleMonitor;
struct SystemEnvironment;

struct ConsoleInfoArg
{
Expand All @@ -86,6 +87,7 @@ struct ConsoleInfoArg
TOPLEFTCOORD TopLeft;
};

#include <memory>
#include "DwmHelper.h"
#include "TaskBar.h"
#include "FrameHolder.h"
Expand Down Expand Up @@ -845,6 +847,11 @@ class CConEmuMain
MSectionLockSimple* pcsLock;
bool wait;
} m_LockConhostStart = {};

public:
void ReloadEnvironmentVariables();
private:
std::shared_ptr<SystemEnvironment> saved_environment_;
};

// Message Logger
Expand Down
12 changes: 7 additions & 5 deletions src/ConEmu/ConEmu.rc
Original file line number Diff line number Diff line change
Expand Up @@ -932,14 +932,16 @@ STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
GROUPBOX "Set up environment variables, cmd.exe aliases, codepage",gbSetAlias,4,1,375,206
GROUPBOX "Set up environment variables, cmd.exe aliases, codepage",gbSetAlias,4,1,375,196
LTEXT "Here you may set up your environment variables, default code page, and so on...\r\nOne line may have only one command! You may comment lines with # sign.",stSetCommands,10,13,363,17,SS_NOPREFIX
LTEXT "set ""PATH=%ConEmuBaseDir%\\Scripts;%PATH%""\r\nchcp utf-8\r\nalias st=start $* -cur_console:n",stSetCommands2,22,32,352,24,SS_NOPREFIX
EDITTEXT tSetCommands,9,61,365,140,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_NOHIDESEL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL
GROUPBOX "Add to %PATH% environment variable",gbAddToPath,4,211,375,28
CONTROL "Add %ConEmuDir% to %PATH%",cbAddConEmu2Path,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,224,176,8
EDITTEXT tSetCommands,9,61,365,130,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_NOHIDESEL | ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL
GROUPBOX "",IDC_STATIC,4,199,375,41
CONTROL "Add %ConEmuDir% to %PATH%",cbAddConEmu2Path,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,210,176,8
CONTROL "Add %ConEmuBaseDir% to %PATH%",cbAddConEmuBase2Path,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194,224,176,8
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,194,210,176,8
CONTROL "Reload environment variables automatically",cbAutoReloadEnvironment,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,225,176,8
END

IDD_SPG_MARKCOPY DIALOGEX 0, 0, 381, 242
Expand Down
3 changes: 3 additions & 0 deletions src/ConEmu/Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ void Settings::InitSettings()
}
}

AutoReloadEnvironment = true;
psEnvironmentSet = lstrdup(
L"set PATH=%ConEmuBaseDir%\\Scripts;%PATH%\r\n"
L"\r\n"
Expand Down Expand Up @@ -2719,6 +2720,7 @@ void Settings::LoadSettings(bool& rbNeedCreateVanilla, const SettingsStorage* ap
//FindComspec(&ComSpec);
//Update Comspec(&ComSpec); --> CSettings::SettingsLoaded

reg->Load(L"AutoReloadEnvironment", AutoReloadEnvironment);
this->LoadMSZ(reg, L"EnvironmentSet", psEnvironmentSet, L"\r\n", true);

reg->Load(L"CTS.Intelligent", isCTSIntelligent);
Expand Down Expand Up @@ -3784,6 +3786,7 @@ BOOL Settings::SaveSettings(BOOL abSilent /*= FALSE*/, const SettingsStorage* ap
reg->Save(L"ComSpec.EnvAddExePath", _bool((ComSpec.AddConEmu2Path & CEAP_AddConEmuExeDir) == CEAP_AddConEmuExeDir));
reg->Save(L"ComSpec.UncPaths", _bool(ComSpec.isAllowUncPaths));
reg->Save(L"ComSpec.Path", ComSpec.ComspecExplicit);
reg->Save(L"AutoReloadEnvironment", AutoReloadEnvironment);
this->SaveMSZ(reg, L"EnvironmentSet", psEnvironmentSet, L"\r\n", false);
reg->Save(L"CTS.Intelligent", isCTSIntelligent);
{
Expand Down
2 changes: 2 additions & 0 deletions src/ConEmu/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ struct Settings

ConEmuComspec ComSpec;

//reg->Load(L"AutoReloadEnvironment", AutoReloadEnvironment);
bool AutoReloadEnvironment;
//reg->LoadMSZ(L"EnvironmentSet", psEnvironmentSet);
wchar_t* psEnvironmentSet; // commands: multiline, "\r\n" separated

Expand Down
13 changes: 13 additions & 0 deletions src/ConEmu/SetDlgButtons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ bool CSetDlgButtons::ProcessButtonClick(HWND hDlg, WORD CB, BYTE uCheck)
case cbComspecUpdateEnv:
OnBtn_ComspecUpdateEnv(hDlg, CB, uCheck);
break;
case cbAutoReloadEnvironment:
OnBtn_AutoReloadEnvironment(hDlg, CB, uCheck);
break;
case cbAddConEmu2Path:
OnBtn_AddConEmu2Path(hDlg, CB, uCheck);
break;
Expand Down Expand Up @@ -2085,6 +2088,16 @@ void CSetDlgButtons::OnBtn_ComspecUpdateEnv(HWND hDlg, WORD CB, BYTE uCheck)
} // cbComspecUpdateEnv


// cbAutoReloadEnvironment
void CSetDlgButtons::OnBtn_AutoReloadEnvironment(HWND hDlg, WORD CB, BYTE uCheck)
{
_ASSERTE(CB==cbAutoReloadEnvironment);

gpSet->AutoReloadEnvironment = uCheck;

} // cbAutoReloadEnvironment


// cbAddConEmu2Path
void CSetDlgButtons::OnBtn_AddConEmu2Path(HWND hDlg, WORD CB, BYTE uCheck)
{
Expand Down
1 change: 1 addition & 0 deletions src/ConEmu/SetDlgButtons.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class CSetDlgButtons : public CDlgItemHelper
static void OnBtn_ComspecTest(HWND hDlg, WORD CB, BYTE uCheck);
static void OnBtn_ComspecBitsRadio(HWND hDlg, WORD CB, BYTE uCheck);
static void OnBtn_ComspecUpdateEnv(HWND hDlg, WORD CB, BYTE uCheck);
static void OnBtn_AutoReloadEnvironment(HWND hDlg, WORD CB, BYTE uCheck);
static void OnBtn_AddConEmu2Path(HWND hDlg, WORD CB, BYTE uCheck);
static void OnBtn_AddConEmuBase2Path(HWND hDlg, WORD CB, BYTE uCheck);
static void OnBtn_ComspecUncPaths(HWND hDlg, WORD CB, BYTE uCheck);
Expand Down
1 change: 1 addition & 0 deletions src/ConEmu/SetPgEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ LRESULT CSetPgEnvironment::OnInitDialog(HWND hDlg, bool abInitial)
{
checkDlgButton(hDlg, cbAddConEmu2Path, (gpSet->ComSpec.AddConEmu2Path & CEAP_AddConEmuExeDir) ? BST_CHECKED : BST_UNCHECKED);
checkDlgButton(hDlg, cbAddConEmuBase2Path, (gpSet->ComSpec.AddConEmu2Path & CEAP_AddConEmuBaseDir) ? BST_CHECKED : BST_UNCHECKED);
checkDlgButton(hDlg, cbAutoReloadEnvironment, (gpSet->AutoReloadEnvironment) ? BST_CHECKED : BST_UNCHECKED);

SetDlgItemText(hDlg, tSetCommands, gpSet->psEnvironmentSet ? gpSet->psEnvironmentSet : L"");

Expand Down
85 changes: 85 additions & 0 deletions src/ConEmu/SystemEnvironment.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@

/*
Copyright (c) 2019-present Maximus5
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the authors may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


#define HIDE_USE_EXCEPTION_INFO
#define SHOWDEBUGSTR

#include "Header.h"
#include <cwctype>

#include "../common/WRegistry.h"
#include "SystemEnvironment.h"

void SystemEnvironment::LoadFromRegistry()
{
env_data.clear();
RegEnumValues(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
SysEnvValueCallback, (LPARAM)this, true);
RegEnumValues(HKEY_CURRENT_USER, L"Environment",
SysEnvValueCallback, (LPARAM)this, true);
}

std::wstring SystemEnvironment::MakeEnvName(const std::wstring& s)
{
// Windows environment names are case-insensitive
std::wstring lc_str; lc_str.reserve(s.size());
for (const auto& c : s)
{
lc_str.push_back(std::towlower(c));
}
return lc_str;
}

bool SystemEnvironment::SysEnvValueCallback(HKEY hk, LPCWSTR pszName, DWORD dwType, LPARAM lParam)
{
if (!pszName || !*pszName || !(dwType == REG_SZ || dwType == REG_EXPAND_SZ))
return true;
CEStr reg_data;
if (RegGetStringValue(hk, nullptr, pszName, reg_data) < 0)
return true;
auto& env_data = ((SystemEnvironment*)lParam)->env_data;
const auto key = MakeEnvName(pszName);
auto& data = env_data[key];
data.expandable = (dwType == REG_EXPAND_SZ);
if (data.name.empty())
data.name = pszName;
if (key == L"path")
{
// concatenate "%PATH%" as "USER;SYSTEM"
if (!reg_data.IsEmpty())
data.data = reg_data.c_str(L"")
+ std::wstring(data.data.empty() ? L"" : L";")
+ data.data;
}
else
{
data.data = reg_data.c_str(L"");
}
return true;
}
Loading

0 comments on commit b295dca

Please sign in to comment.