【问题标题】:IExpress Post Installation Batch with NodeJS not finding NPM immediately使用 NodeJS 的 IExpress 安装后批处理未立即找到 NPM
【发布时间】:2018-08-15 23:34:22
【问题描述】:

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

iExpress 包只是安装包节点:

msiexec /i node.msi

然后运行 ​​Post Installation Batch 以将 Javascript 放入 %UserProfile% 文件夹中的文件夹中。

安装后批处理运行时: cmd /c post_install.bat

批处理中有一行不工作:

npm install <dependency>

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

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

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

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

【问题讨论】:

标签: node.js windows batch-file windows-installer iexpress


【解决方案1】:

What is the reason for '...' is not recognized as an internal or external command, operable program or batch file? 上的答案解释了 systemuser 环境变量在 Windows 注册表中的存储位置以及如何对其进行更新。它还解释了没有进程可以修改已经运行的进程的环境变量,并且每个新进程都会继承其父进程的当前环境变量列表。

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

IExpress 安装过程运行 msiexec /i node.msi,它安装 Node.js 并很可能添加或修改 systemuser Windows 注册表中的环境变量。但是对整台机器和当前用户的持久存储环境变量的修改不会自动转移到已经运行的IExpress安装过程的本地环境变量列表中。

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

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

但是post_install.bat执行的npm批处理文件依赖于Node.js安装过程中存储在Windows注册表中的环境变量。因此,在执行npm 批处理之前,有必要使用 systemuser 环境变量(按此顺序)更新 local 环境变量文件。

这可以通过使用以下注释代码扩展 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 注册表中的 systemuser 环境变量,并更新 local 环境变量,包括 local PATH 甚至可以在 Windows XP / Windows Server 2003 上工作,尽管与 Windows Vista / Server 2008 和所有更高版本的 Windows 相比,REG 在 Windows XP / Server 2003 上的输出有所不同。

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

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

【讨论】:

    【解决方案2】:

    这对于评论来说太长了,尽管老实说,我是在评论而不是在回答。尽最大努力,有几件事:

    1. 安全iExpress suffers from some major security vulnerabilities。如果这打击了您的客户,那真的是一件可怕的事情。只是我的两美分和友好的单挑。
    2. SendMessageTimeout:即使成功应用,环境变量更新也不会立即适用于系统上所有正在运行的应用程序。
    3. Chris Painter:我没有跟上 NodeJS 的速度。希望 Chris Painter 知道如何正确部署此类脚本,我怀疑还有另一种比您使用的更可靠的方法。不过他现在可能不会潜伏在这里。

    更新:使用a link 对上述问题添加了注释,说明如何使用高级安装程序部署 Node.js。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-10
      • 1970-01-01
      • 2023-03-23
      • 2015-11-19
      • 1970-01-01
      • 2016-03-25
      • 2023-03-24
      • 1970-01-01
      相关资源
      最近更新 更多