如何从Inno Setup安装程序设置全局环境变量?

时间:2014-08-13 14:36:42

标签: environment-variables inno-setup

如何在Inno Setup中设置全局环境变量?

背景:我正在使用Inno安装实用程序,需要在进行实际安装之前设置一个全局环境变量。

3 个答案:

答案 0 :(得分:13)

试试这个:

[Registry]
Root: HKCU; Subkey: "Environment"; ValueType:string; ValueName: "VARIABLE_NAME"; \
    ValueData: "new_value"; Flags: preservestringtype

您可能需要添加以下内容:

[Setup]
; Tell Windows Explorer to reload the environment
ChangesEnvironment=yes

或者尝试:

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

参考:Inno Setup Frequently Asked Questions - Setting Environment Variables

如果未传播变量更改(请参阅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 '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);
end;

更多详情:

Inno Setup: Setting a System Environment Variable

  

在更现代(换句话说,正确)的操作系统下,例如   Windows 2000,XP和Windows 2003 Server,环境变量都是   存储在注册表中的密钥如下:

     

HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \                      环境

     

通过在此键或下创建新值来添加变量   修改值(如果已存在)。要删除变量,请执行   只需删除其注册表值,除非您要删除部分内容   扩展值,例如PATH,在这种情况下,您只删除该部件   你想要的。

     

此时,除非您,否则Windows不会知道您的更改   注销或重启。为了解决这个问题,SetEnv将广播一个    WM_SETTINGCHANGE 到系统中的所有窗口。这允许   其他正在运行的应用程序 - 例如,Explorer.exe-将被通知   你的改变。如果从命令提示符运行SetEnv,则不会   更新当前DOS窗口的环境变量。这是   主要是由于一个进程(SetEnv)无法改变的事实   其父级环境(命令提示符)。但是,任何新的   DOS /命令提示您打开将显示新变量/值。

答案 1 :(得分:4)

运行两个setup.exe时会出现什么问题,第一个执行设置环境变量,第二个执行真正设置所需的操作。第一个将使用setup.exe / VERYSILENT

运行

我正在添加一个系统范围的环境变量:

[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

答案 2 :(得分:3)

@ Adrian的回答中的解决方案(实际上是从@TLama's answer to similar question复制的)在许多情况下都是正确的。

runasoriginaluser flag [Run]任务对runasoriginaluser任务不起作用(postinstall flag隐含的内容)。即该变量不会传播到运行的应用程序,该应用程序使用常见的"运行我的程序" 复选框"已完成"页。

原因是SetEnvironmentVariable的任务由Inno Setup安装程序的未提升的隐藏父进程执行。 runasoriginaluser将更改安装程序的环境,但不会更改其父进程的环境。不幸的是,安装程序的父进程无法控制(imo)。

作为解决方法,要为cmd.exe任务设置变量,必须在安装程序父进程和任务之间注入一个中间进程,并让中间进程设置变量。

这样的中间过程很容易成为[Run] Filename: "{cmd}"; Parameters: "/C set MYVAR=MyValue & ""{app}\MyProg.exe"""; \ Description: "Run My Program"; Flags: postinstall runhidden 及其set command

cmd.exe

runhidden flag隐藏Payment控制台窗口,而不是应用程序(假设它是GUI应用程序)。如果它是控制台应用程序,请使用start在自己的(可见)控制台窗口中启动它。