IExpress Post 使用 NodeJS 的安装批处理没有立即找到 NPM

IExpress Post Installation Batch with NodeJS not finding NPM immediately

我正在尝试使用 iExpress 在我在 NodeJS 上创建的小脚本上安装依赖项。

iExpress 包只安装包节点:

msiexec /i node.msi

然后 运行 进行 Post 安装批处理,将 Javascript 放入 %UserProfile% 文件夹中的文件夹中。

Post 安装批次 运行 具有: cmd /c post_install.bat

批处理中有一行不起作用:

npm install <dependency>

这似乎不会在 MSI 安装后立即起作用,但它会在 .exe 为 运行 并安装 NodeJS 时第二次起作用。

因此,无论出于何种原因,MSI 直到批处理完成后才设置 PATH 变量,或者 iExpress Post 安装批处理未设置正确的环境变量。

其他人遇到过这个问题,是否有解决方法或建议?

我应该将 MSI 的安装和 NPM 的 运行ning 放入安装脚本中而不是使用 Post 安装吗?

这对于评论来说太长了,尽管老实说我评论多于回答。尽力而为,一些事情:

  1. 安全性iExpress suffers from some major security vulnerabilities。如果这影响了您的客户,那将是一件非常糟糕的事情。只是我的两分钱和友好的单挑。
    • 这同样适用于此处讨论的许多自解压安装程序工具:Error Creating a 7-zip installer package(link 仅供参考,您不需要它)。
    • 建议您使用成熟且维护良好的部署工具:Tools Discussion and links all over the place and a Tools List(仅简化的主要工具)。上次访问link推荐。
  2. SendMessageTimeout:环境变量更新不会立即对系统上的所有 运行 应用程序可用,即使已成功应用.
  3. Chris Painter:我跟不上 NodeJS 的速度。希望 Chris Painter 知道如何正确部署此类脚本,我怀疑还有另一种方法比您使用的方法更可靠。不过他现在可能不会潜伏在这里

UPDATE: Added a comment to the question above with which shows how Node.js can be deployed using Advanced Installer.

上的答案解释了 systemuser 环境变量存储在 Windows 注册表中的位置,并且如何对它们进行更新。它还解释了没有进程可以修改已经存在的 运行 进程的环境变量,并且每个新进程都继承其父进程的当前环境变量列表。

所以在启动 IExpress 安装过程时,此安装过程从其父进程继承环境变量,通常是 Windows Explorer,但也可以是 www 浏览器或任何其他应用程序。

IExpress 安装过程运行 msiexec /i node.msi 安装 Node.js 并且很可能添加或修改 [= Windows 注册表中的 49=]system 或 user 环境变量。但是那些对整个机器和当前用户的持久存储环境变量的修改不会自动接管到已经 运行 IExpress[=86 的 local 环境变量列表=] 安装过程.

下一步由 IExpress 安装进程启动,一个带有命令行 cmd /c post_install.bat 的命令进程通过 Windows 获取当前设置的环境变量的新副本IExpress 安装过程。

因此,无论 Node.js 安装过程在 Windows 注册表中修改的持久存储 systemuser 环境变量或 local 环境变量 MSIEXEC 进程对 Windows 不可见执行批处理文件的命令进程 post_install.bat.

但是 post_install.bat 执行的 npm 批处理文件依赖于 Node.js 安装过程中存储在 Windows 注册表中的环境变量.因此,有必要使用 systemuser 环境变量更新 local 环境变量(在此命令)在执行 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%\System32\reg.exe query "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" 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%\System32\reg.exe query "HKEY_CURRENT_USER\Environment" 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 注册表中的环境变量并更新 local 环境变量包括 local PATH 即使在 Windows XP / Windows Server 2003 上也能工作,尽管输出 REG 在 Windows XP / Server 2003 上与 Windows Vista / Server 2008 和所有更高的 Windows 版本不同。

要了解使用的命令及其工作原理,请打开命令提示符 window,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • call /?
  • cd /?
  • echo /?
  • endlocal /?
  • for /?
  • if /?
  • reg /?
  • reg query /?
  • rem /?
  • set /?
  • setlocal /?