Skip to content

Instantly share code, notes, and snippets.

@UweRaabe
Created June 16, 2026 09:38
Show Gist options
  • Select an option

  • Save UweRaabe/6fc7eff86a76c875a06bc9b5d5e04886 to your computer and use it in GitHub Desktop.

Select an option

Save UweRaabe/6fc7eff86a76c875a06bc9b5d5e04886 to your computer and use it in GitHub Desktop.
Making the IDE reload environment variables
unit IDE.EnvironmentVariables;
interface
uses
System.Win.Registry,
System.Classes;
type
TCustomEnvironmentVars = class(TStringList)
const
cDialogName = 'TDefaultEnvironmentDialog';
cAreaEN = 'IDE';
cAreaDE = 'IDE';
cAreaFR = 'IDE';
cAreaJP = 'IDE';
cPageNameEN = 'Environment Variables';
cPageNameDE = 'Umgebungsvariablen';
cPageNameFR = 'Variables d''environnement';
cPageNameJP = '環境変数';
cSubKey = 'Environment Variables';
private
FReg: TRegistry;
FRegBaseKey: string;
class procedure CloseDialog(const AClassName: string); static;
function GetReg: TRegistry;
class procedure StartDialogWatcher;
strict protected
function GetValue(const AName: string): string;
procedure SetValue(const AName, AValue: string);
public
constructor Create(const ARegBaseKey: string);
class function Area: string;
class function PageName: string;
class procedure ReloadFromRegistry;
property Reg: TRegistry read GetReg;
property RegBaseKey: string read FRegBaseKey;
end;
implementation
uses
Winapi.Windows,
System.SysUtils, System.StrUtils, System.Threading,
Vcl.Forms, Vcl.Controls,
ToolsAPI;
type
OTA = record
public
class function Services: IOTAServices; static;
end;
class function OTA.Services: IOTAServices;
begin
BorlandIDEServices.GetService(IOTAServices, Result);
end;
constructor TCustomEnvironmentVars.Create(const ARegBaseKey: string);
begin
inherited Create;
FRegBaseKey := ARegBaseKey;
if Reg.OpenKey(IncludeTrailingBackslash(RegBaseKey) + cSubKey, False) then begin
Reg.GetValueNames(Self);
end;
end;
class function TCustomEnvironmentVars.Area: string;
begin
case IndexText(GetLocaleOverride(''), ['DE', 'FR', 'JP']) of
0: Result := cAreaDE;
1: Result := cAreaFR;
2: Result := cAreaJP;
else
Result := cAreaEN;
end;
end;
class procedure TCustomEnvironmentVars.CloseDialog(const AClassName: string);
begin
if Application = nil then Exit;
if Application.Terminated then Exit;
var form := Screen.ActiveForm;
if form <> nil then begin
if form.ClassNameIs(AClassName) then
form.Perform(CM_DIALOGKEY, VK_ESCAPE, 0);
end;
end;
function TCustomEnvironmentVars.GetReg: TRegistry;
begin
if FReg = nil then begin
FReg := TRegistry.Create;
end;
Result := FReg;
end;
function TCustomEnvironmentVars.GetValue(const AName: string): string;
begin
Result := Reg.ReadString(AName);
end;
class function TCustomEnvironmentVars.PageName: string;
begin
case IndexText(GetLocaleOverride(''), ['DE', 'FR', 'JP']) of
0: Result := cPageNameDE;
1: Result := cPageNameFR;
2: Result := cPageNameJP;
else
Result := cPageNameEN;
end;
end;
class procedure TCustomEnvironmentVars.ReloadFromRegistry;
begin
{ To make the IDE adopt our changes to the Environment Variables in the registry
we need to open the Tools - Options dialog, select the Environment Variables page
and close it either by pressing OK or Cancel.
As it is a modal dialog, the closing is done automatically inside StartDialogWatcher.
}
StartDialogWatcher;
OTA.Services.GetEnvironmentOptions.EditOptions(Area, PageName);
end;
procedure TCustomEnvironmentVars.SetValue(const AName, AValue: string);
begin
Reg.WriteString(AName, AValue);
end;
class procedure TCustomEnvironmentVars.StartDialogWatcher;
{ Starts a background task waiting for the environment options dialog
just to close this dialog emulating an ESC key press.
We just wait for a changed ActiveFormHandle
}
begin
var lastActiveFormHandle := Application.ActiveFormHandle;
TTask.Run(
procedure
var
finished: Boolean;
begin
finished := False;
repeat
Sleep(1);
if Application.Terminated then Exit;
TThread.Synchronize(nil,
procedure
begin
if Application.Terminated then begin
finished := True;
end
else if lastActiveFormHandle <> Application.ActiveFormHandle then begin
lastActiveFormHandle := Application.ActiveFormHandle;
CloseDialog(cDialogName);
finished := True;
end;
end);
until finished;
end);
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment