Old 15th July 2015, 10:00   #1
Stefano Mtangoo
Junior Member
 
Join Date: Jul 2015
Posts: 6
Reloading System Path after running another Installer

I just jumped into NSIS few days ago and am getting used to this awesome installer. My Installer need to install NodeJs and Run series of Commands against npm to install some packaging. I know how to do all those, which brings me to my problem.

When I invoke NodeJs.msi via ExecWait, it modifies the System path adding its path, but after it exits I cannot get it in my current environment so my subsequent commend fails miserably

I'm finding a way to reload system path after installing nodejs or at least to to get nodejs path added.

Is that possible? Is that even the way am supposed to do with NSIS?

Thanks,
S!
Stefano Mtangoo is offline   Reply With Quote
Old 15th July 2015, 10:37   #2
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,150
There is no single function that does what you want, you would have to read from the two registry locations, combine the results and call SetEnvironmentVariable. All of this has to be done with the system plugin to avoid NSIS string length limitations...

What is the minimum Windows version you need to support?

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 15th July 2015, 11:14   #3
Stefano Mtangoo
Junior Member
 
Join Date: Jul 2015
Posts: 6
Quote:
Originally Posted by Anders View Post
There is no single function that does what you want, you would have to read from the two registry locations, combine the results and call SetEnvironmentVariable. All of this has to be done with the system plugin to avoid NSIS string length limitations...
Thanks for answering. Though I have not grasped the full weight of your answer, it gives me a bit of light in the issue. If you can coin simple code examples it will really be of great help.

Quote:
Originally Posted by Anders View Post
What is the minimum Windows version you need to support?
I only Support Windows XP up. I don't care about Windows vista too, if it will be problematic.
Only XP, 7, 8 and definitely later 10 is my concern right now.

Again thank you!
Stefano Mtangoo is offline   Reply With Quote
Old 15th July 2015, 13:08   #4
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,150
When reading from the registry you need to expand the strings and newer versions of Windows have better helper function for that. Are you using NSIS v3 or v2.46?

It is undocumented but SHGetValue and SHQueryValueEx should expand for you...

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Old 15th July 2015, 14:28   #5
Stefano Mtangoo
Junior Member
 
Join Date: Jul 2015
Posts: 6
Quote:
Originally Posted by Anders View Post
When reading from the registry you need to expand the strings and newer versions of Windows have better helper function for that. Are you using NSIS v3 or v2.46?

It is undocumented but SHGetValue and SHQueryValueEx should expand for you...
I use 3.0b1 but I don't mind upgrading/Downgrading.
At this point am just as pragmatic as I can get
Stefano Mtangoo is offline   Reply With Quote
Old 15th July 2015, 18:16   #6
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
Doesn't Node.js create a proper registry entry with (only) it's full installation path somehwere?

If it does, you better read the Node.js installation path from the registry explicitly and then use that to build a fully-qualified path to the executable which you want to run. This way more reliably then relying (hoping) that your executable happens to be on %PATH%.

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 15th July 2015, 18:26   #7
Stefano Mtangoo
Junior Member
 
Join Date: Jul 2015
Posts: 6
I have asked them even before posting here and have not answered.
I searched with REGEDIT but with no avail.

Do you know any other way?
Stefano Mtangoo is offline   Reply With Quote
Old 15th July 2015, 18:38   #8
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
HKEY_CURRENT_USER\Software\Node.js\InstallPath

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI
LoRd_MuldeR is offline   Reply With Quote
Old 15th July 2015, 18:53   #9
Stefano Mtangoo
Junior Member
 
Join Date: Jul 2015
Posts: 6
Wow Thank you.
I now put it this way after installer quits
PHP Code:
;add new environment added by Nodejs
ReadRegStr 
$0 HKCU "Software\Node.js" "InstallPath"
ReadEnvStr $R0 "PATH"
StrCpy $R0 "$R0;$0"
System::Call 'Kernel32::SetEnvironmentVariableA(t, t) i("PATH", R0).r0' 
Stefano Mtangoo is offline   Reply With Quote
Old 15th July 2015, 18:57   #10
LoRd_MuldeR
Major Dude
 
LoRd_MuldeR's Avatar
 
Join Date: Sep 2005
Location: Somewhere over the Slaughterhouse
Posts: 797
It's very bad idea to extend %PATH% like this. That's because NSIS strings are limited to a length of 1024 chars (might be a bit longer, if you use "long string" special build). This means you will easily end up with truncated %PATH%, if your %PATH% happens to be long.

Why work with %PATH% anyway? It's highly unreliable to launch a program without a full path and hope that the system will pick up the proper program from %PATH% (or whatever the "current directory" happens to be). Use a fully-qualified path whenever you can!

I suggest you do something like this, if possible for your situation:
code:
ReadRegStr $0 HKCU "Software\Node.js" "InstallPath"
Exec[Wait] '"$0\node.exe" your_parameters_here'




Note this info from Microsoft documentation on CreateProcess() function:

If the file name does not contain a directory path, the system searches for the executable file in the following sequence:
  1. The directory from which the application loaded.
  2. The current directory for the parent process.
  3. The 32-bit Windows system directory.
  4. The 16-bit Windows system directory.
  5. The Windows directory.
  6. The directories that are listed in the PATH environment variable.

My Plugins: StdUtils | NSISList | CPUFeatures | ExecTimeout | KillProc
My source of inspiration: http://youtu.be/lCwY4_0W1YI

Last edited by LoRd_MuldeR; 15th July 2015 at 21:56.
LoRd_MuldeR is offline   Reply With Quote
Old 15th July 2015, 19:15   #11
Stefano Mtangoo
Junior Member
 
Join Date: Jul 2015
Posts: 6
Thanks a lot. my problem is solved.
NSIS is really great!
Stefano Mtangoo is offline   Reply With Quote
Old 17th July 2015, 16:25   #12
Anders
Moderator
 
Anders's Avatar
 
Join Date: Jun 2002
Location: ${NSISDIR}
Posts: 5,150
If you cannot detect the path and need to use the new %Path% (very much untested):

Quote:

!include LogicLib.nsh
!include WinCore.nsh
!ifndef NSIS_CHAR_SIZE
!define NSIS_CHAR_SIZE 1
!define SYSTYP_PTR i
!else
!define SYSTYP_PTR p
!endif
!ifndef ERROR_MORE_DATA
!define ERROR_MORE_DATA 234
!endif
/*!ifndef KEY_READ
!define KEY_READ 0x20019
!endif*/


Function RegReadExpandStringAlloc
System::Store S
Pop $R2 ; reg value
Pop $R3 ; reg path
Pop $R4 ; reg hkey
System::Alloc 1 ; mem
StrCpy $3 0 ; size
loop:
System::Call 'SHLWAPI::SHGetValue(${SYSTYP_PTR}R4,tR3,tR2,i0,${SYSTYP_PTR}sr2,*ir3r3)i.r0' ; NOTE: Requires SHLWAPI 4.70 (IE 3.01+ / Win95OSR2+)
${If} $0 = 0
Push $2
Push $0
${Else}
System::Free $2
${If} $0 = ${ERROR_MORE_DATA}
IntOp $3 $3 + ${NSIS_CHAR_SIZE} ; Make sure there is room for SHGetValue to \0 terminate
System::Alloc $3
Goto loop
${Else}
Push $0
${EndIf}
${EndIf}
System::Store L
FunctionEnd

Function RefreshProcessEnvironmentPath
System::Store S
Push ${HKEY_CURRENT_USER}
Push "Environment"
Push "Path"
Call RegReadExpandStringAlloc
Pop $0
${IfThen} $0 <> 0 ${|} System::Call *(i0)${SYSTYP_PTR}.s ${|}
Pop $1
Push ${HKEY_LOCAL_MACHINE}
Push "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Push "Path"
Call RegReadExpandStringAlloc
Pop $0
${IfThen} $0 <> 0 ${|} System::Call *(i0)${SYSTYP_PTR}.s ${|}
Pop $2
System::Call 'KERNEL32::lstrlen(t)(${SYSTYP_PTR}r1)i.R1'
System::Call 'KERNEL32::lstrlen(t)(${SYSTYP_PTR}r2)i.R2'
System::Call '*(&t$R2 "",&t$R1 "",i)${SYSTYP_PTR}.r0' ; The i is 4 bytes, enough for a ';' separator and a '\0' terminator (Unicode)
StrCpy $3 ""
${If} $R1 <> 0
${AndIf} $R2 <> 0
StrCpy $3 ";"
${EndIf}
System::Call 'USER32::wsprintf(${SYSTYP_PTR}r0,t"%s%s%s",${SYSTYP_PTR}r2,tr3,${SYSTYP_PTR}r1)?c'
System::Free $1
System::Free $2
System::Call 'KERNEL32::SetEnvironmentVariable(t"PATH",${SYSTYP_PTR}r0)'
System::Free $0
System::Store L
FunctionEnd

Section
Call RefreshProcessEnvironmentPath
SectionEnd

IntOp $PostCount $PostCount + 1
Anders is offline   Reply With Quote
Reply
Go Back   Winamp & Shoutcast Forums > Developer Center > NSIS Discussion

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump