node.jswindowsbatch-filewindows-installeriexpress

IExpress Post Installation Batch with NodeJS not finding NPM immediately


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?


Solution

  • 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.