我有一个license.exe文件,我最后在设置代码中调用
代码需要在正确工作之前设置环境变量,
代码如下:
[Registry]
; set PATH
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \
ValueType: string; ValueName: "PATH"; ValueData: "{app}"
[Setup]
; Tell Windows Explorer to reload the environment
ChangesEnvironment=yes
[Run]
Filename: "{app}\temp\installation_files\license.exe";
此处代码执行,但找不到正确的路径。
当我检查系统环境变量时,它已正确设置,
当我手动运行license.exe
代码后,它可以正常工作并查看环境变量。
有人可以告诉我如何解决这个问题吗?
或者如何在系统识别环境变量之前延迟[Run]
部分?
答案 0 :(得分:7)
为执行[Run]
部分中的条目而创建的进程继承了其父进程的环境块,即安装程序本身。因此,您必须将环境变量设置为安装程序,并让它继承到您执行的应用程序。如何做到如下所示:
[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;
通知系统其余部分有关变量变化的上一个答案:
正如@Jerry在评论中指出的那样,在处理[Run]
部分后会执行有关环境变化的通知。实际上,安装程序执行one of the last things。
因此,要在处理[Run]
部分之前通知系统环境更改,您需要有一个解决方法。我重写了从Inno Setup代码到脚本的RefreshEnvironment
过程。如果您将ChangesEnvironment
指令设置为yes
,则它与执行的功能相同。
在以下脚本中,我删除了ChangesEnvironment
指令,并在注册表项的AfterInstall
参数函数中添加了RefreshEnvironment
过程的执行:
[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 '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;
答案 1 :(得分:2)
TLama's answer中SetEnvironmentVariable
的解决方案在许多情况下都是正确的。
但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隐藏aobj = new ByteArray();
aobj.writeObject(Obj); //Obj is a usual as3 Object {param1:123,......}
控制台窗口,而不是应用程序(假设它是GUI应用程序)。如果它是控制台应用程序,请使用start
在自己的(可见)控制台窗口中启动它。
答案 2 :(得分:1)
经过以下一些修改,效果很好:
[Run]
Filename: "{app}\{#MyAppExeName}"; BeforeInstall: AppendToPathAndRefresh;Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}";Flags: nowait postinstall shellexec skipifsilent
[Code]
////////////////////////////////////////////////////////////
const
SMTO_ABORTIFHUNG = 2;
WM_WININICHANGE = $001A;
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_WININICHANGE, 0,
PAnsiChar(S), SMTO_ABORTIFHUNG, 5000, MsgResult);
end;
///PATH ENVINRONMENT//////////////////////////////////////////
function Replace(Dest, SubStr, Str: string): string;
var
Position: Integer;
Ok: Integer;
begin
Ok := 1;
while Ok > 0 do
begin
Position:=Pos(SubStr, Dest);
if Position > 0 then
begin
Delete(Dest, Position, Length(SubStr));
Insert(Str, Dest, Position);
end else
Ok := 0;
end;
Result:=Dest;
end;
procedure AppendToPath();
var
V: string;
Str: string;
begin
RegQueryStringValue(HKLM, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path', V)
Str := ExpandConstant('{app}\libav');
V := Replace(V, Str, '');
V := V + ';' + Str;
V := Replace(V,';;',';');
RegWriteStringValue(HKLM, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path', V)
// MsgBox(V, mbInformation, MB_OK);
end;
procedure RemoveFromPath();
var
V: string;
Str: string;
begin
RegQueryStringValue(HKLM, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path', V)
Str := ExpandConstant('{app}\dlls');
V := Replace(V, Str, '');
V := Replace(V,';;',';');
RegWriteStringValue(HKLM, 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path', V)
//MsgBox(V, mbInformation, MB_OK);
end;
procedure AppendToPathAndRefresh;
begin
AppendToPath;
RefreshEnvironment;
end;
procedure DeinitializeUninstall();
begin
RemoveFromPath();
end;
///END OF PATH ENVIRONMENT ///////////////////////////////////