Created
June 16, 2026 09:38
-
-
Save UweRaabe/6fc7eff86a76c875a06bc9b5d5e04886 to your computer and use it in GitHub Desktop.
Making the IDE reload environment variables
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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