Search code examples
jrubyenvironment-variablesnsis

NSIS - jruby fails to access environment variables


I've made a NSIS script to create an installer for a Rails application. The application uses JRuby and Java.

In the first section of the installer I set the environment variables: I add jruby\bin to PATH and I create JAVA_HOME variable, which points to Java\jre6.

!define JRubyBinPath "$PROGRAMFILES\${PRODUCT_PUBLISHER}\JRuby\jruby-1.6.3\bin"

Function SetEnvVars    
    # set JAVA_HOME
    ${EnvVarUpdate} $0 "JAVA_HOME" "A" "HKCU" "C:\Program Files\Java\jre6"  
    # add jruby to Path
    ${EnvVarUpdate} $0 "Path" "A" "HKLM" "${JRubyBinPath}"          
FunctionEnd

Section "Pre" SEC01     
    Call SetEnvVars 
    ...
SectionEnd

** All the paths are correct. **

In the second section of the installer, after packing all the application files and JRuby files, I initialize the database using the following commands:

Section "Installer" SEC02

...

    SetOutPath $INSTDIR
    nsExec::ExecToLog "jruby -S bundle exec rake db:create RAILS_ENV=production"
    nsExec::ExecToLog "jruby -S bundle exec rake db:migrate RAILS_ENV=production"
    nsExec::ExecToLog "jruby -S bundle exec rake db:seed RAILS_ENV=production"      

...

SectionEnd

The problem is that when I run the installer on a clean Windows system, all the code executes correctly, except for the lines that contain commands using "jruby". I get no error in the installer window, it just won't execute those lines.

Anyway, if I manually run those commands in a console right after the installer finishes, everything works as expected.

From what I have seen so far, the problem is that the installer cannot access the environment variables until it finishes.

* What I have done so far to solve this problem is creating the main installer Installer.exe (here I pack all the files and I set the environment variables), and another executable Init.exe which initializes the database. If I manually run these executables - first Installer.exe then Init.exe - the application installs correctly. But if I try to launch Init.exe from Installer.exe, it won't work.

However, if there would be a way to execute the "jruby" commands in a new/different thread than the one that sets the environment variables, I think the problem would be solved. But I still couldn't find the way to do that.

Thanks.


Solution

  • NSIS doesn't have any threading. Apparently not quite true—but in your own code, you don't get to use threads.

    You may need to set PATH for the current process; I'm not familiar with ${EnvVarUpdate}, but looking at its script it doesn't seem to updates the variable in the current process. Try this:

    ${EnvVarUpdate} $0 PATH A HKLM "${JRubyBinPath}"  # The line you already have
    System::Call Kernel32::SetEnvironmentVariable(t"PATH",tr0)
    

    Another note: you are hard-coding JRubyBinPath; are you sure you really want to do that?