繁体   English   中英

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

[英]How to set a global environment variable from Inno Setup installer?

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

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

尝试这个:

[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 常见问题-设置环境变量

如果未传播变量更改(请参阅Inno Setup 中 [Run] 程序的环境变量未识别 [不可用]

[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:设置系统环境变量

在更现代的(换句话说,适当的)操作系统下,例如 Windows 2000、XP 和 Windows 2003 Server,环境变量存储在注册表中的以下项下:

HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\ Environment

通过在此键下创建新值或修改已存在的值来添加变量。 要删除一个变量,您只需删除它的注册表值,除非您要删除扩展值的一部分,例如 PATH,在这种情况下,您只需删除您想要的部分。

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

运行两个 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

@Adrian 的回答中的解决方案(实际上是从@TLama 对类似问题的回答中复制)在许多情况下都是正确的。

但它不适用于带有runasoriginaluser标志的[Run]任务( postinstall flag所暗示的内容)。 即该变量不会传播到使用“已完成”页面上常见的“运行我的程序”复选框运行的应用程序。

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

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

这样的中间过程可以很容易地成为cmd.exe及其set命令

[Run]
Filename: "{cmd}"; Parameters: "/C set MYVAR=MyValue & ""{app}\MyProg.exe"""; \
    Description: "Run My Program"; Flags: postinstall runhidden

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM