How to set a global environment variable from Inno Setup installer?
Try this:
[Registry]
Root: HKCU; Subkey: "Environment"; ValueType:string; ValueName: "VARIABLE_NAME"; \
ValueData: "new_value"; Flags: preservestringtype
You might need to add this:
[Setup]
; Tell Windows Explorer to reload the environment
ChangesEnvironment=yes
Alternatively try:
[Run]
Filename: "{app}\MyProg.exe"; BeforeInstall: SetEnvPath
[Code]
#ifdef UNICODE
#define AW "W"
#else
#define AW "A"
#endif
function SetEnvironmentVariable(lpName: string; lpValue: string): BOOL;
external 'SetEnvironmentVariable{#AW}@kernel32.dll stdcall';
procedure SetEnvPath;
begin
if not SetEnvironmentVariable('VARIABLE_NAME', 'new_value') then
MsgBox(SysErrorMessage(DLLGetLastError), mbError, MB_OK);
end;
Reference: Inno Setup Frequently Asked Questions - Setting Environment Variables
If the variable change is not propagated (see Environment variable not recognized [not available] for [Run] programs in Inno Setup)
[Run]
...; AfterInstall: RefreshEnvironment
[Code]
const
SMTO_ABORTIFHUNG = 2;
WM_WININICHANGE = $001A;
WM_SETTINGCHANGE = WM_WININICHANGE;
type
WPARAM = UINT_PTR;
LPARAM = INT_PTR;
LRESULT = INT_PTR;
function SendTextMessageTimeout(hWnd: HWND; Msg: UINT;
wParam: WPARAM; lParam: PAnsiChar; fuFlags: UINT;
uTimeout: UINT; out lpdwResult: DWORD): LRESULT;
external '[email protected] stdcall';
procedure RefreshEnvironment;
var
S: AnsiString;
MsgResult: DWORD;
begin
S := 'Environment';
SendTextMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
PAnsiChar(S), SMTO_ABORTIFHUNG, 5000, MsgResult);
end;
More details:
Inno Setup: Setting a System Environment Variable
Under more modern (in other words, proper) operating systems, such as Windows 2000, XP, and Windows 2003 Server, environment variables are stored in the Registry under the following key:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\ Environment
Variables are added by creating a new value under this key or by modifying a value if it already exists. To delete a variable, you simply delete its Registry value, unless you are removing part of an expanded value, such as PATH, in which case you only remove the part you want.
At this point, Windows will not be aware of your changes unless you log off or reboot. To get around this, SetEnv will broadcast a WM_SETTINGCHANGE to all of the windows in the system. This allows other running applications—for example, Explorer.exe—to be notified of your change. If you run SetEnv from a command prompt, this will not update the environment variable for the current DOS window. This is mainly due to the fact that a process (SetEnv) cannot change the environment of its parent (The Command Prompt). However, any new DOS/Command Prompts that you open will show the new variable/value.
What would be wrong with running two setup.exe with the first one doing the setting of the environment variables, and the second doing the things needed for the true setup. The first one would be run with setup.exe /VERYSILENT
I am doing to add an system wide environment variable:
[Setup]
; Tell Windows Explorer to reload the environment
ChangesEnvironment=True
[Registry]
Root: "HKLM"; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: string; ValueName: "EGPL_GeoLibrarian_Drive"; ValueData: "L"; Flags: createvalueifdoesntexist preservestringtype
The solutions in @Adrian's answer (actually copied from @TLama's answer to similar question) are correct for many situations.
But it won't work for [Run]
tasks with runasoriginaluser
flag (what is implied by postinstall
flag). I.e. the variable won't be propagated to an application run with common "Run My Program" check box on the "Finished" page.
The reason is that the tasks with runasoriginaluser
are executed by a un-elevated hidden parent process of the Inno Setup installer. The SetEnvironmentVariable
will change environment for the installer, but not for its parent process. Unfortunately, the parent process of the installer cannot be controlled (imo).
As a workaround, to set the variable for the runasoriginaluser
tasks, you have to inject an intermediate process between the installer parent process and the task, and have the intermediate process set the variable.
Such an intermediate process can easily be the cmd.exe
with its set
command:
[Run]
Filename: "{cmd}"; Parameters: "/C set MYVAR=MyValue & ""{app}\MyProg.exe"""; \
Description: "Run My Program"; Flags: postinstall runhidden
The runhidden
flag hides the cmd.exe
console window, not the application (assuming it's a GUI application). If it's a console application, use start
to start it in its own (visible) console window.