在Inno Setup中[Run]程序无法识别[不可用]环境变量

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Inno Setup中[Run]程序无法识别[不可用]环境变量相关的知识,希望对你有一定的参考价值。

我有一个license.exe文件,我最后在我的设置代码中调用,

在正常工作之前,代码需要设置环境变量,

代码如下:

[Registry]
; set PATH
Root: HKLM; Subkey: "SYSTEMCurrentControlSetControlSession ManagerEnvironment"; 
    ValueType: string; ValueName: "PATH"; ValueData: "{app}"

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

[Run]
Filename: "{app}	empinstallation_fileslicense.exe";

这里代码执行,但找不到正确的路径。

当我检查系统环境变量时,它设置正确,

当我手动运行license.exe代码后,它可以正常工作并查看环境变量。

谁能告诉我如何解决这个问题?

或者如何延迟[Run]部分直到系统识别环境变量?

答案

为从[Run]部分执行条目而创建的进程继承了其父进程的环境块,即安装程序本身。因此,您必须将环境变量设置为安装程序,并让它继承到您执行的应用程序。如何做到这一点如下面的脚本所示:

[Run]
Filename: "{app}	empinstallation_fileslicense.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;

以前的答案用于通知系统其余部分有关变量的变化:

正如@Jerry在他的评论中所指出的,在处理[Run]部分之后会执行有关环境变化的通知。实际上,它是由安装程序执行的one of the last things

因此,要在处理[Run]部分之前通知系统环境更改,您需要有一个解决方法。我重写了从Inno Setup代码到脚本的RefreshEnvironment程序。如果你将ChangesEnvironment指令设置为yes,它的功能与执行的功能相同。

在下面的脚本中,我删除了ChangesEnvironment指令,并从注册表项的RefreshEnvironment参数函数中添加了AfterInstall过程的执行:

[Registry]
Root: HKLM; Subkey: "SYSTEMCurrentControlSetControlSession ManagerEnvironment"; 
    ValueType: string; ValueName: "PATH"; ValueData: "{app}"; 
    AfterInstall: RefreshEnvironment;

[Run]
Filename: "{app}	empinstallation_fileslicense.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 '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;
另一答案

SetEnvironmentVariable中使用TLama's answer的解决方案在许多情况下都是正确的。

但它对[Run]runasoriginaluser flag任务不起作用(postinstall flag暗示的是什么)。即该变量不会传播到使用“完成”页面上的常用“运行我的程序”复选框运行的应用程序。

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

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

这样的中间过程很容易成为cmd.exe及其set command

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

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

以上是关于在Inno Setup中[Run]程序无法识别[不可用]环境变量的主要内容,如果未能解决你的问题,请参考以下文章

inno setup里在[run]中如何使用install实现静默安装?

Inno Setup 3 :语法解析

Inno setup打包软件run段了存在.EXE或者.BAT问题?

Inno Setup 临时部署的 Java 安装程序包含在安装大小中

Inno Setup

Inno Setup Section [Run] with condition