Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Persisting an environment variable through Ruby

I am trying to set my DOS environment variable in Ruby, and have it persist after the script exits. For example, if I want a ruby script set_abc_env.rb to set environment variable 'ABC' to 'blah', I expect to run the following:

C:> echo %ABC%
C:> set_abc_env.rb
C:> echo %ABC% blah

How do I do this?

like image 603
user24560 Avatar asked Oct 10 '08 04:10

user24560


2 Answers

You can access environment variables via Ruby ENV object:

i = ENV['ABC']; # nil
ENV['ABC'] = '123';
i = ENV['ABC']; # '123'

Bad news is, as MSDN says, a process can never directly change the environment variables of another process that is not a child of that process. So when script exits, you lose all changes it did.

Good news is what Microsoft Windows stores environment variables in the registry and it's possible to propagate environment variables to the system. This is a way to modify user environment variables:

require 'win32/registry.rb'

Win32::Registry::HKEY_CURRENT_USER.open('Environment', Win32::Registry::KEY_WRITE) do |reg|
  reg['ABC'] = '123'
end

The documentation also says you should log off and log back on or broadcast a WM_SETTINGCHANGE message to make changes seen to applications. This is how broadcasting can be done in Ruby:

require 'Win32API'  

SendMessageTimeout = Win32API.new('user32', 'SendMessageTimeout', 'LLLPLLP', 'L') 
HWND_BROADCAST = 0xffff
WM_SETTINGCHANGE = 0x001A
SMTO_ABORTIFHUNG = 2
result = 0
SendMessageTimeout.call(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 'Environment', SMTO_ABORTIFHUNG, 5000, result)  
like image 174
Alexander Prokofyev Avatar answered Oct 20 '22 01:10

Alexander Prokofyev


For anyone else looking for a solution for this and looking for a more of a hack that doesn't require logging in or out I came up with this solution for a similar problem :

WORKAROUND:

My work around is dependent on combination of ruby and a command line utility called SETENV.EXE develped by Vincent Fatica. It's more than a decade old at this point but works fine in windows XP ( didn't test under Windows 7 yet). It works better than setx utility available from MS IMHO. At lest for deleting stuff. Make sure setenv is available from command line. Put it in some c:\tools and put c:\tools in your PATH.

Here is a short example of a method using it:

def switch_ruby_env
  if RUBY_VERSION.match("1.8.7").nil?  
    `setenv -m CUSTOM_PATH " "`
  else
    `setenv -m CUSTOM_PATH -delete`
  end
end 
like image 1
konung Avatar answered Oct 20 '22 01:10

konung