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?
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)
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With