IExpress Post Installation Batch with NodeJS not finding NPM immediately

ぐ巨炮叔叔 提交于 2020-01-04 13:40:20

问题


I'm trying to use iExpress to install dependencies on a small script that I've created on NodeJS.

The iExpress package simply installs the packages Node:

msiexec /i node.msi

Then runs a Post installation Batch to put the Javascript into a folder in the %UserProfile% folder.

The Post installation Batch is run with: cmd /c post_install.bat

In the batch there is a line which isn't working:

npm install <dependency>

This doesn't seem to work immediately after the MSI install, but it will work the second time the .exe is run and NodeJS is installed.

So for whatever reason, either the MSI isn't setting the PATH variables until after the Batch is finished, or the iExpress Post Installation batch isn't getting set with the right environmental variables.

Anyone else experienced this problem, is there a work around or recommendation?

Should I put the installation of the MSI and the running of NPM into an installation script instead of using the Post Install?

Thanks for your help.


回答1:


The answer on What is the reason for '...' is not recognized as an internal or external command, operable program or batch file? explains where system and user environment variables are stored in Windows registry and how updates are made on them. It also explains that no process can modify the environment variables of an already running process and each new process inherits the current list of environment variables of its parent process.

So on starting IExpress installation process this installation process inherits the environment variables from its parent process which is usually Windows Explorer, but can be also a www browser or any other application.

The IExpress installation process runs msiexec /i node.msi which installs Node.js and most likely adds or modifies system or user environment variables in Windows registry. But those modifications on persistent stored environment variables for entire machine and current user are not automatically taken over to local environment variables list of already running IExpress installation process.

Next is started by IExpress installation process a command process with command line cmd /c post_install.bat which gets by Windows a fresh copy of environment variables as currently set for IExpress installation process to work with.

So whatever the Node.js installation process modified in Windows registry on the persistent stored system and user environment variables or on local environment variables of MSIEXEC process is not visible for the Windows command process executing the batch file post_install.bat.

But npm batch file executed by post_install.bat depends on environment variables stored in Windows registry during Node.js installation process. For that reason it is necessary to update local environment variables with the system and user environment variables (in this order) before executing npm batch file.

This can be done by extending post_install.bat with following commented code:

@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

This batch file reading system and user environment variables as currently stored in Windows registry and updating the local environment variables including local PATH works even on Windows XP / Windows Server 2003 although output of REG is different on Windows XP / Server 2003 in comparison to Windows Vista / Server 2008 and all later Windows versions.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

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



回答2:


This became too long for a comment, though I am honestly commenting more than answering. Best effort though, a few things:

  1. Security: iExpress suffers from some major security vulnerabilities. If this hits your clients, it really is a terrible thing to deal with. Just my two cents and friendly heads-up.
    • The same applies to many self-extracting installer tools as discussed here: Error Creating a 7-zip installer package (link for reference only, you should not need it).
    • Recommend you go with an established and properly maintained deployment tool: Tools Discussion and links all over the place and a Tools List (simplified, major tools only). A visit to the last link recommended.
  2. SendMessageTimeout: Environment variable updates are not immediately available for all running applications on the system, even if successfully applied.
    • Supposedly you can use the SendMessageTimeout API to update all running windows with new settings and variables. I am not sure how reliable this really is - I remember some problems back in the day of Win9X, but I am no expert on the subject.
    • Maybe have a look here: https://www.advancedinstaller.com/forums/viewtopic.php?t=27578. This is a very good message board belonging to Advanced Installer.
    • WiX features the WixBroadcastSettingChange and WixBroadcastEnvironmentChange Custom Actions (which I have never tried). I believe its core implementation is here: BroadcastSettingsChange.cpp.
    • In essence: calling SendMessageTimeout API should make the PATH change "stick".
  3. Chris Painter: I am not up to speed on NodeJS. Hopefully Chris Painter will know how to deploy such scripts properly, I suspect there is another way that is more reliable than what you use. He may not be lurking here at the moment though.

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



来源:https://stackoverflow.com/questions/51867784/iexpress-post-installation-batch-with-nodejs-not-finding-npm-immediately

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!