Environment variable not recognized [not available] for [Run] programs in Inno Setup

The processes created for executing entries from the [Run] section inherits the environment block of its parent process, which is the installer itself. So you have to set the environment variable to the installer and let it inherit to your executed application. How to do that is shown in the below script:

[Run]
Filename: "{app}\temp\installation_files\license.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('PATH', ExpandConstant('{app}')) then
    MsgBox(SysErrorMessage(DLLGetLastError), mbError, MB_OK);
end;

Previous answer for notifying rest of the system about variable change:

As @Jerry pointed out in his comment, a notification about the environment changes is performed after the [Run] section is processed. Actually, it is one of the last things executed by the installer.

So, to notify the system about environment changes before processing the [Run] section, you'll need to have a workaround. I rewrote the RefreshEnvironment procedure from Inno Setup code to script. It's the same function as it's executed if you have ChangesEnvironment directive set to yes.

In the following script I have removed the ChangesEnvironment directive and added execution of the RefreshEnvironment procedure from the AfterInstall parameter function of your registry entry:

[Registry]
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \
    ValueType: string; ValueName: "PATH"; ValueData: "{app}"; \
    AfterInstall: RefreshEnvironment;

[Run]
Filename: "{app}\temp\installation_files\license.exe";

[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;

The solution with SetEnvironmentVariable in TLama's answer is 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 PATH=%PATH%;{app} & ""{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 and you want the output to be visible, remove the runhidden flag. Alternatively, you can use start command to start the application in its own console window.