windows 通过 Ruby 持久化环境变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/190168/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 11:25:38  来源:igfitidea点击:

Persisting an environment variable through Ruby

windowsrubyenvironment-variablesdos

提问by user24560

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.rbto set environment variable 'ABC' to 'blah', I expect to run the following:

我正在尝试在 Ruby 中设置我的 DOS 环境变量,并在脚本退出后保持它。例如,如果我想要一个 ruby​​ 脚本set_abc_env.rb将环境变量 'ABC' 设置为 'blah',我希望运行以下命令:

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

How do I do this?

我该怎么做呢?

回答by Alexander Prokofyev

You can access environment variables via Ruby ENV object:

您可以通过 Ruby ENV 对象访问环境变量:

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.

坏消息是,正如 MSDN所说,一个进程永远不能直接更改不是该进程子进程的另一个进程的环境变量。因此,当脚本退出时,您会丢失它所做的所有更改。

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

好消息是 Microsoft Windows 将环境变量存储在注册表中,并且可以将环境变量传播到系统。这是一种修改用户环境变量的方法:

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:

该文档还说您应该注销并重新登录或广播 WM_SETTINGCHANGE 消息以对应用程序进行更改。这就是在 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)  

回答by konung

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.EXEdevelped 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.

我的工作依赖于 ruby​​ 和Vincent Fatica 开发的名为SETENV.EXE的命令行实用程序的组合。此时它已有十多年的历史,但在 Windows XP 中运行良好(尚未在 Windows 7 下测试)。它比 MS 恕我直言提供的 setx 实用程序更有效。至少是为了删除东西。确保可以从命令行使用 setenv。把它放在一些 c:\tools 中,然后把 c:\tools 放在你的 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