簡體   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