I am trying to use environment variables that I set inside the [registry] section of my Inno Setup installer, and then use those environment variables inside the [Run] section by running windows cmds such as postgres psql and node commands to setup my node service / configure my postgres database and user.
How can I refresh the environment variables for the current Inno setup installer during the [Run] Section?
The problem is that when Inno opens a cmd process to run my commands, the environment variables haven't taken effect because the terminal uses the parent's session env var(which don't update) even though I use ChangesEnvironment=yes and calling RefreshEnvironment procedure. I need these environement variables to properly configure my database and my node service using pm2.
The RefreshEnvironment runs this code:
procedure RefreshEnvironment;
var
S: AnsiString;
MsgResult: DWORD;
begin
S := 'Environment';
SendTextMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
PAnsiChar(S), SMTO_ABORTIFHUNG, 5000, MsgResult);
end;
EDIT UPDATE
This is an example of my current code:
#define POSTGRES_PATH_ENV_VAR "C:\Program Files\PostgreSQL\11\bin"
[Registry]
; Path Env Vars
; Postgres commands
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \
ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{#POSTGRES_PATH_ENV_VAR}"; \
Check: NeedsAddPath('{#POSTGRES_PATH_ENV_VAR}')
[Run]
; Install Postgres
Filename: "{tmp}\{#POSTGRES}"; StatusMsg: "Installing Postgres..."; BeforeInstall: RefreshEnvironment();
; Configure Postgres after installation
Filename: "{cmd}"; Parameters: "/k """"{#POSTGRES_PATH_ENV_VAR}\psql"" -c ""CREATE USER {code:GetPostgresEnvVar|2} WITH PASSWORD 'testingPassword';"" -U postgres & \
""{#POSTGRES_PATH_ENV_VAR}\psql"" -c ""CREATE DATABASE testUser OWNER postgres"" -U postgres"""; StatusMsg: "Configuring PostgreSQL..."; Flags: shellexec runascurrentuser waituntilterminated
The Path variable does not get updated and psql cannot be found unless I use a absolute path using the POSTGRES_PATH_ENV_VAR global variable.
I also can't get this to work with installing node js inside the installer then running npm command. Here is a full script of attempting to get it to work:
EDIT 2
I got node to work with using setEnvironmentVariable. But when I try to add a second path for psql then neither of them work? How can I get more than one env var added using setEnvironmentVariable?
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "Test"
#define MyAppVersion "0.2.0"
#define MyAppPublisher "Blarg"
; Programs
#define NODE "node-v10.16.0-x64.msi"
#define POSTGRES_PATH_ENV_VAR "C:\Program Files\PostgreSQL\11\bin"
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{33B47B4D-F4A9-43F5-BF97-8A485232253C}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
; AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
DefaultDirName=C:\Program Files\TestingApp\{#MyAppName}
DisableDirPage=yes
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
; Uncomment the following line to run in non administrative install mode (install for current user only.)
; PrivilegesRequired=lowest
OutputDir=C:\Users\Joel\Desktop
OutputBaseFilename=Test-Installer-{#MyAppVersion}
Compression=lzma
SolidCompression=yes
WizardStyle=modern
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Files]
Source: "installation_files\{#NODE}"; DestDir: "{tmp}"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
[Run]
; Install Node
Filename: "{sys}\msiexec.exe"; Parameters: "/i ""{tmp}\{#NODE}"""; StatusMsg: "Installing Node.Js...";
; Install Postgres
; Postgres Configuring and run first time setup if database creates successfully
Filename: "{cmd}"; Parameters: "/k node -v && npm -v && psql"; StatusMsg: "Testing Node and Psql..."; BeforeInstall: SetEnvPath; Flags: shellexec runascurrentuser waituntilterminated;
[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 'SendMessageTimeoutA@user32.dll stdcall';
procedure RefreshEnvironment;
var
S: AnsiString;
MsgResult: DWORD;
begin
S := 'Environment';
SendTextMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
PAnsiChar(S), SMTO_ABORTIFHUNG, 5000, MsgResult);
MsgBox('Refreshed Environment Variables.', mbInformation, MB_OK);
end;
#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('PATH', 'C:\Program Files\nodejs\') then
MsgBox(SysErrorMessage(DLLGetLastError), mbError, MB_OK);
if not SetEnvironmentVariable('PATH', '{#POSTGRES_PATH_ENV_VAR}') then
MsgBox(SysErrorMessage(DLLGetLastError), mbError, MB_OK);
end;