我正在尝试使用iExpress在NodeJS上创建的一个小脚本上安装依赖项。
iExpress软件包只需安装软件包节点:
msiexec /i node.msi
然后运行安装后批处理,将Javascript放入%UserProfile%文件夹中的一个文件夹中。
安装后批处理运行时使用:cmd /c post_install.bat
批次中有一行不起作用:
npm install <dependency>
这似乎不会在MSI安装后立即工作,但它会在第二次运行.exe并安装NodeJS时工作。
因此,无论出于何种原因,要么MSI直到批处理完成后才设置PATH变量,要么iExpress安装后批处理没有设置正确的环境变量。
其他人也遇到过这个问题,有没有解决办法或建议?
我应该把MSI的安装和NPM的运行放在安装脚本中,而不是使用后安装吗?
关于"…"的原因是什么的答案是否未被识别为内部或外部命令、可操作程序或批处理文件?解释了系统和用户环境变量存储在Windows注册表中的位置,以及如何对它们进行更新。它还解释说,任何进程都不能修改已经运行的进程的环境变量,并且每个新进程都继承其父进程的当前环境变量列表。
因此,在启动IExpress安装过程时,此安装过程从其父进程继承环境变量,该父进程通常是Windows资源管理器,但也可以是www浏览器或任何其他应用程序。
IExpress安装过程运行msiexec /i node.msi
,它安装Node.js,并且很可能在Windows注册表中添加或修改系统或用户环境变量。但是,对整个机器和当前用户的持久存储环境变量的修改不会自动转移到已运行IExpress安装过程的本地环境变量列表中。
接下来由IExpress安装进程启动,该进程是一个带有命令行cmd /c post_install.bat
的命令进程,它通过Windows获取当前设置的环境变量的新副本,供IE xpress装进程使用。
因此,无论在持久存储的系统和用户环境变量上的Windows注册表中修改了Node.js安装过程,还是在MSIEXEC进程的local环境变量上,对于执行批处理文件post_install.bat
的Windows命令进程都不可见。
但是post_install.bat
执行的npm
批处理文件依赖于Node.js安装过程中存储在Windows注册表中的环境变量。因此,在执行npm
批处理文件之前,有必要使用系统和用户环境变量(按此顺序)更新本地的环境变量。
这可以通过使用以下注释代码扩展post_install.bat
来实现:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Set current directory to user's profile directory.
cd /D "%UserProfile%"
rem Make sure the environment variables used to build local PATH from
rem the PATH environment variables currently stored in Windows registry
rem do not already exist with unwanted values.
set "LocalPath="
set "SystemPath="
set "UserPath="
rem Get all system environment variables as currently stored in Windows
rem registry and set them in local environment with exception of system PATH.
for /F "skip=2 tokens=1,2*" %%A in ('%SystemRoot%System32reg.exe query "HKLMSystemCurrentControlSetControlSession ManagerEnvironment" 2^>nul') do (
if /I "%%A" == "Path" (
set "SystemPath=%%C"
) else if /I "%%B" == "REG_SZ" (
set "%%A=%%C"
) else if /I "%%B" == "REG_EXPAND_SZ" (
call set "%%A=%%C"
)
)
rem Get all user environment variables as currently stored in Windows
rem registry and set them in local environment with exception of user PATH.
for /F "skip=2 tokens=1,2*" %%A in ('%SystemRoot%System32reg.exe query "HKEY_CURRENT_USEREnvironment" 2^>nul') do (
if /I "%%A" == "Path" (
set "UserPath=%%C"
) else if /I "%%B" == "REG_SZ" (
set "%%A=%%C"
) else if /I "%%B" == "REG_EXPAND_SZ" (
call set "%%A=%%C"
)
)
rem PATH can contain references to environment variables which can be
rem expanded only after having all environment variables except system
rem and user PATH already set in local environment. Now it is possible
rem to expand the environment variable references in system and user
rem PATH and concatenate them two one PATH set in local environment
rem replacing PATH as inherited from process starting this batch file.
if not defined SystemPath goto ProcessUserPath
call set "LocalPath=%SystemPath%"
if not "%LocalPath:~-1%" == ";" set "LocalPath=%LocalPath%;"
:ProcessUserPath
if not defined UserPath goto SetLocalPath
call set "LocalPath=%LocalPath%%UserPath%"
:SetLocalPath
if not defined LocalPath goto DoInstall
if "%LocalPath:~-1%" == ";" set "LocalPath=%LocalPath:~0,-1%"
if defined LocalPath set "PATH=%LocalPath%"
:DoInstall
rem Call NPM in its own environment inherited from current local environment.
rem Then discard all modifications made by NPM batch file on its own local
rem environment and restore the environment this batch file has set before.
setlocal
call npm.cmd install ...
endlocal
rem Insert here other post installation commands.
rem Restore previous environment on starting this batch file which means
rem discarding all modifications made on local list of environment variables
rem and restoring initial current directory before modification by CD at top
rem and restoring initial status of command extensions and delayed expansion.
endlocal
此批处理文件读取当前存储在Windows注册表中的系统和用户环境变量,并更新包括本地PATH
在内的本地环境变量,即使在Windows XP/Windows Server 2003上也能工作,尽管REG在Windows XP/Server 2003上的输出与Windows Vista不同/Server 2008和所有更高版本的Windows。
为了理解所使用的命令及其工作方式,请打开命令提示符窗口,在那里执行以下命令,并非常仔细地阅读为每个命令显示的所有帮助页面。
call /?
cd /?
echo /?
endlocal /?
for /?
if /?
reg /?
reg query /?
rem /?
set /?
setlocal /?
这对评论来说太长了,尽管我只是诚实地评论而不是回答。尽管尽了最大努力,但有几件事:
-
安全
:iExpress存在一些主要的安全漏洞。如果这件事袭击了你的客户,那真的是一件可怕的事情。只有我的两美分和友好的抬头。
- 这同样适用于这里讨论的许多自解压安装程序工具:创建7-zip安装程序包时出错(链接仅供参考,您不需要它)
- 建议您使用一个已建立并正确维护的部署工具:到处都是工具讨论和链接,以及工具列表(仅限简化的主要工具)。建议访问最后一个链接
-
SendMessageTimeout
:即使成功应用,系统上所有正在运行的应用程序也无法立即使用环境变量更新。
- 假设您可以使用
SendMessageTimeout
API使用新设置和变量更新所有正在运行的窗口。我不确定这到底有多可靠——我记得Win9X时代的一些问题,但我不是这方面的专家 - 也许可以看看这里:https://www.advancedinstaller.com/forums/viewtopic.php?t=27578.这是一个非常好的留言板属于高级安装程序
- WiX具有WixBroadcastSettingChange和WixBroadcast EnvironmentChange自定义操作(我从未尝试过)。我相信它的核心实现在这里:BroadcastSettingsChange.cpp
- 本质上:调用
SendMessageTimeout
API应该使PATH更改"粘"住
- 假设您可以使用
- Chris Painter :我在NodeJS上没有跟上进度。希望Chris Painter知道如何正确部署这样的脚本,我怀疑还有另一种方法比你使用的更可靠。不过他现在可能不潜伏在这里
UPDATE:为上面的问题添加了一条注释,并添加了一个链接,显示如何使用Advanced Installer部署Node.js。