IExpress Post Installation Batch with NodeJS not finding NPM immediately - node.js

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?

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 /?

This became too long for a comment, though I am honestly commenting more than answering. Best effort though, a few things:
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.
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".
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.

Related

Running npm in cmd giving me errors, I just installed nodejs msi on windows

I installed nodejs in Windows system from official website and npm giving errors:
CALL "C:\Program Files\node js\\node.exe" "C:\Program Files\nodejs\\node_modules\npm\bin\npm-cli.js" prefix -g' is not
recognized as an internal or external command, operable program or batch file.
I have given all sorts of paths. Please help me.
http://prntscr.com/gso39z
Add the following paths to your PATH environment variable
%USERPROFILE%\AppData\Roaming\npm
C:\Program Files\nodejs\
(note that i have windows 10, where your programs are installed can differ as per your windows version)
To permanently set PATH environment variable, follow these steps:
This PC/ My Computer Properties
Advanced System Settings, (right side)
from popup, click environment variable
select PATH environment variable under system variable, (not user variable) then click edit
Click new, and copy and paste one of the path (given) there.
new again and paste second path
to check if its set or not, goto terminal, and type PATH
note: if you type PATH, its value will be displayed, but if you type %PATH% , each of its value will act as a command input to terminal (windows terminal -_-).
Start the process by being an administrator.
Open up your command prompt as an administrator.
And if you are using older version of node say 6.9, please upgrade to 6.10, it may solve your problem.

How can I suppress “Terminate batch job (Y/N)” confirmation in PowerShell?

When I press Ctrl+C in PowerShell, I receive:
Terminate batch job (Y/N)?
Similar to https://superuser.com/questions/35698/how-to-supress-terminate-batch-job-y-n-confirmation, except for Windows PowerShell.
Does PowerShell provide any more control over batch jobs than what CMD does?
The behavior is neither caused by PowerShell nor can PowerShell change it (as evidenced by the PowerShell source-code repo not containing the prompt message).
The behavior is built into cmd.exe - Powershell, in this case, is calling a .cmd file (batch file), which is interpreted by cmd.exe.
If you explicitly control the invocation of the target executable, you can fix this by moving to Powershell - note this has its own considerations, see below.
If you do not explicitly control the invocation of the target executable, you're out of luck (unless you're willing to install third-party cmd.exe replacements) and must press Ctrl+C twice in order to terminate execution.
A[n ill-advised] workaround is to modify the cmd.exe binary - see article with instructions on how to patch the cmd.exe executable in order to suppress the prompt. Additionally, you can post a feature request on GitHub to request that this behavior be fixed at the source, though that is unlikely to happen for reasons of backward compatbility.
To demonstrate the behavior:
The examples assume that Node.js is installed and that node.exe is therefore in your PATH:
First, invoke node.exe directly, with a tight loop that requires you to press Ctrl+C to terminate the process.
PS> node -e "while (true);"
As you'll see, pressing Ctrl+C instantly terminates the process - no confirmation prompt.
Now, let's create a sample batch file that invokes the same command and invoke that batch file:
PS> "#echo off`nnode -e `"while (true);`"" | Set-Content test.cmd
PS> ./test.cmd
As you'll see, pressing Ctrl+C now presents the undesired Terminate batch job (Y/N)? prompt. (You'd get the same behavior if you ran the batch file from cmd.exe.)
To demonstrate that gulp is a cmd file:
You say you're running your command via gulp's CLI.
On Windows, the entry point for the gulp CLI is gulp.cmd [see update in the bottom section] - i.e., a batch file. That is how it works in general for npm-package "binaries" (executables) implemented as either JS files or shell scripts.
That gulp invokes gulp.cmd can be verified as follows:
# Execute from a project folder that has `gulp` installed as a dependency.
# If `gulp` is installed *globally*
# Note: CLI `npx` requires npm version 5.2.0+
PS C:\some\NodeJs\project> npx where gulp
You'll see something like:
C:\some\NodeJs\project\node_modules\.bin\gulp
C:\some\NodeJs\project\node_modules\.bin\gulp.cmd
Note that where.exe also lists the extension-less Unix-shell script, ...\gulp; however, from cmd.exe / Powershell such a shell script isn't directly executable, and it is ...\gulp.cmd - the batch file - that is executed.
(If in doubt, place a command such as #set /p dummy="Press a key" at the start of the gulp.cmd file, and you'll see that this command executes when you invoke gulp without the .cmd extension.
Also note that there is no gulp.exe.)
More generally, on Windows, a project's node_modules\.bin subfolder contains pairs of CLI entry points for the CLIs that come with packages that the project depends on locally:
node_modules\.bin\<some-cli> is the Unix shell script (whose executing interpreter is controlled via its shebang line).
node_modules\.bin\<some-cli>.cmd is the helper batch file for Windows.
Updates and future considerations:
In the context of npm modules, the problem would go away if a PowerShell script (*.ps1) were used as the helper script on Windows. There are tickets for npm, yarn and similar software to do this. There are also some drawbacks:
*.ps1 files aren't directly executable from outside of PowerShell, notably from cmd.exe and File Explorer (and changing that is nontrivial).
PowerShell still hasn't fully replaced cmd.exe as the default shell, as of Windows 10 (and won't anytime soon, if ever).
When called from PowerShell, a *.ps1 file would be found and run in-process, so a possible solution is for the npm project to also provide *.ps1 helper scripts, which would take precedence over *.cmd files of the same name.
Update:
Recent versions of npm (verified in 6.14.10) indeed DO install such *.ps1 files.
Alternative package manager yarn, since v2 does not seem to use batch files anymore at all, so the original problem is bypassed there; (v1, by contrast, still uses batch files (only); upgrading from v1 must be done on a per-project basis see the migration instructions).
As the other answer notes, the correct fix is to replace cmd scripts with ps1 versions.
However another workaround for users of the Hyper shell is 'Hyper yes', a plugin that automatically hits y for you when the prompt comes up.
best way to avoid it is to not start it, in my case, is not to type npm run devStart but instead type nodemon ./server.js localhost 3000
here's how it looks like
#echo off
start /w "" "C:\myfile.bat" 2>nul|findstr /i "termin"
if errorlevel 1 goto bypass
:bypass
echo hello by stexup YouTube channel!
timeout /t 5 >nul

How to disable an extra window to restart system even after selecting not to do so in files in use dialog in installshield

I am doing an upgrade for the existing exe file using installshield. when installing the update , in files in use dialog I select the option to automatically close and restart the application instead of the other option to reboot the system.
But I get an extra window which tells me to restart the system again after installation is complete. How to disable this window? Please help :)
You can try to run the installation silently with REBOOT=ReallySuppress (update the paths). Please note that I haven't had the chance to test all these command lines:
msiexec.exe /I "C:\IsWiX.msi" /QN /L*V "C:\msilog.log" REBOOT=ReallySuppress
/I is for install
/QN is silent mode
/L* is verbose logging
If you have an EXE file instead of an MSI file I would extract the MSI to an administrative image (file extract from setup.exe basically) using the following command:
setup.exe /a
Then specify an extract location for the files in the EXE file. You can also run it directly with the Installshield command lines for EXE files. Something like:
Setup.exe /v"REBOOT=ReallySuppress /qn"
Or silently with logging:
Setup.exe /v"/l*v c:\test.log REBOOT=ReallySuppress /qn"
There are also some simplified command line macros from Microsoft. Most of the time these can be used. Other times you need the full command line interface.

Running node.js code just displays a node identifier

I have the following code in a file called server.js.
var http = require('http');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World\n');
}).listen(8124);
console.log('Server running at http://127.0.0.1:8124/');
I use the command prompt and naviage to the folder where the file recides and then the run the command
node server.js
But I don't get the expected output. Instead I get
The node identifier for {My Machine Name} is v2hrfnqaj.
Note: I already have node installed in my machine and it was working fine.
Was getting this when I was trying to run cordova commands. Steps to resolve:
Windows
In CMD prompt, type "where node". As Michael mentioned, this shows
you the likely culprit, that you have 2 nodejs EXEs installed on
your machine.
Navigate to Start > Computer > Right-click Properties > Advanced system settings
Under the Advanced tab, select Environment Variables
Under System variables, select "Path" variable
Find nodejs EXE, usually "C:\Program Files (x86)\nodejs\"
Cut and paste this to the beginning of the "Path" variable. Ensure
the paths are separated by a ";"
Open a new CMD prompt and try cordova again
This happens when Harvest SCM is installed on your system. It has an executable with the name node.exe at <Program Files (x86)>\CA\SharedComponents\PEC\bin (where <Program Files (x86)> is your x86 program files folder). This path is present in your PATH variable before the path to Node.js's node.exe.
Update: You don't need the elaborate scheme listed in the old answer. You just have to open the Command Prompt and run:
C:\> nodevars
nodevars.bat is a small script that does essentially the same thing described below (but in a safer way). If you have node installed, this script should be in path. (If not make sure to add C:\Program Files\nodejs to your path. But make sure to append it in the end so Harvest SCM does not break).
Everything below is outdated, but I will leave it for the curious reader.
You can do either of following two things you can do to overcome this problem:
Remove <Program Files (x86)>\CA\SharedComponents\PEC\bin from PATH environment variable.
Add/move <Program Files (x86)>\nodejs to the beginning of the PATH environment variable (This is the currently accepted answer from djrpascu).
You can do better!
There are two problems with the above approaches:
You break Harvest SCM's functionality.
If you do not have elevated privileges to change PATH, you are out of options. (Thanks #Glats)
So I created this little batch file, and put it in a directory where I have several other personal scripts (this directory is in my PATH). Here's the gist for the script.
nodecmd.bat
#echo off
set path=%path:C:\Program Files (x86)\CA\SharedComponents\PEC\bin;=%;C:\Program Files (x86)\nodejs;
start %ComSpec%
Then the next time you want to run Node.js, instead of Command Prompt, you open the new script with "Run..." command.
Windows+R
nodecmd
A command prompt will appear. You can use this command prompt to run node without a hassle.
Explanation
This bit deletes the Harvest's executable's path from PATH variable:
%path:C:\Program Files (x86)\CA\SharedComponents\PEC\bin;=%;
And this adds the Node.js's path:
set path=...;C:\Program Files (x86)\nodejs;
The result is a string that contains the original PATH variable minus Harvest's path, plus Node's path. And it is set as PATH variable in the scope of current batch file.
Note: You might have to change the path's in the script to suit software installation folders in your system).
Next line, start %ComSpec% starts a Command Prompt. By this time, the PATH variabe is modified. With modified environment variables, you can run node within this new Command Prompt. The environment variable modification does not affect the rest of the system, making sure that Harvest SCM software runs without breaking.
Don't break your Harvest SCM by removing it from path. Try this one, open your windows command line (cmd) and then pass the following nodejs batch file so that it will set your command line to nodejs environment. Enjoy the node commands there.
C:> "C:\Program Files\nodejs\nodevars.bat"
You can also prioritize in the environments.
Steps:
Computer -> Right click -> Properties -> Advanced system settings -> Environment variables -> PATH(in system variables list) -> Edit -> Prioritize by moving up
This is old, but I ran into this same problem. Exact same message (with my machine name of course). The issue was that there was another node executable on the path, in C:\Program Files (x86)\CA\SharedComponents\PEC\bin. I'm on a windows machine, so running where node showed the two conflicting "node" executables in the path.
To fix the problem, I just removed the CA directory from the PATH environment variable.
I faced the same problem and simply changed the the name of node.exe file from Harvest. This hasn't broken anything from Harvest and I can keep working with it.
Change the Harvest's command name to node_.exe:
ren "C:\Program Files (x86)\CA\SharedComponents\PEC\bin\node.exe" "C:\Program Files (x86)\CA\SharedComponents\PEC\bin\node_.exe"
I think you're running the wrong node command.
Try locating or re-downloading your nodejs installation and add it to your path as the first directory. If you're running linux or unix you can try 'which node' to see what is being run.
Note that in some cases, the node.js executable is called nodejs so you may want to try
nodejs server.js as well
I used the node.js command prompt, instead of the windows default command prompt and it worked for me. Did not know why it did't work in the windows default command prompt.
I was also running with same issue - while defining the path for windows use below parameter
Windows:
set NODE_PATH=C:\nodejs
OR
Set the environment variable for nodejs
NODE_PATH=C:\nodejs
Path= C:\nodejs
(append the path contain this string “c:\nodejs”)

Environment Variable not being passed to CruiseControl, specifically the 'nodosfilewarnings' ENV variable from Cygwin

I have a Perl program that someone else created and I am calling on with CruiseControl. The program calls on Unix Commands using Cygwin. However, everytime that the Perl program calls on a Unix like command with a DOS like address, I get the well known error:
cygwin warning:
MS-DOS style path detected: E:\regression
Preferred POSIX equivalent is: /cygdrive/e/regression
CYGWIN environment variable option "nodosfilewarning" turns off this warning.
Consult the user's guide for more details about POSIX paths:
http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
I have set both the User Variable AND System Variable CYGWIN to nodosfilewarning. This removes the error when I run the program from the command line, but the error still occurs in CruiseControl when called as an automated process from a batch file. I have called on both the batch file from the Desktop AND Command Line and ran as an administrator. Nothing changes.
Other Notes
For purposes of this problem, I don't have access to the Perl Program
I am trying to go back to Cygwin 1.5.*, but since I am using Server 2008, I am encountering compatibility issues
This is occurring on one of the distributed servers, not the main server running the Webdashboard.
I have read somewhere that this issue may stem from a different user calling on CruiseControl, but the issue should have been solved by setting this as an ENV System variable
Is it possible to modify the registery to set the ENV variables?
Thank you in advance
The way I do it is like this
printf 'export CYGWIN=nodosfilewarning' >> ~/.bash_profile
If CruiseControl is connecting to the server via ssh, reinstall sshd and explicitly include nodosfilewarning when prompted for the CYGWIN environment variable during the install.
Re-installing with modified environment will work but if you don't want to or cannot re-install, an alternative is to change the registry instead of re-installing the service.
See: CYGWIN windows cygrunsrv sshd server and MS-DOS style path detected

Resources