プロセス固有の環境変数(PATH)を設定したコマンドプロンプトを立ち上げる


概要

よく使うツール群のパスがなぜか通ってないけど、
・システムの環境変数(PATH)をいじりたいくない
・コマンドプロンプトごとに適宜切り替えたい
ということがあったので、プロセス固有の環境変数(PATH)を設定したプロンプトを立ち上げるようにします。

これを、rubyのsetrbvars.batを題材にvbscriptやrbで書いてみます。

コード - vbscript

ポイントとなるコードをvbscriptで示します。rbでもwin32oleを使うのでだいたい同じです。応用例2参照

cmd_after_addpath.vbs
'利用するオブジェクトを生成しておく
set shell = CreateObject("WScript.Shell")
set fso   = CreateObject("Scripting.FileSystemObject") 'path_to_addに設定するもの次第ではfsoはなくてもOK

'このスクリプトがあるフォルダをパスに追加する
path_to_add = fso.getParentFolderName(WScript.ScriptFullName)

' たちあげたプロンプトにだけ一時的に追加したいのでEnvironment("Process")にしておく。
set env = shell.Environment("Process")
env.Item("PATH") =  path_to_add & ";" & env.item("PATH")

' cmd.exeを実行する
shell.Run "cmd.exe /K", ,FALSE

cmd.exeのパラメータに/Kを指定してるのは、

Cmd - DOS コマンド一覧 - Programming Field

/K <command>
<command> で指定した内容を実行します。実行をした後、「このコマンドを実行したcmd.exe」は終了せず、引き続きプロンプトを表示します。

ということを利用して、コマンドプロンプトに出てしまうロゴ(↓)を出さなようにするためです。

ロゴ
Microsoft Windows [Version xx.y.zzzzzzzz]
(c) 201y Microsoft Corporation. All rights reserved.

改造すると自分なりのロゴを出すために使えます。
たとえば、以下のようにすると追加したパスをロゴ代わりに出します。

改造
' cmd.exeを実行する
shell.Run "cmd.exe /K echo " & path_to_add & " is temporary added to PATH", ,FALSE

応用例1

setrbvars.vbs
'利用するオブジェクトを生成しておく
set shell = CreateObject("WScript.Shell")
set fso   = CreateObject("Scripting.FileSystemObject") 'path_to_addに設定するもの次第ではfsoはなくてもOK

'このスクリプトがあるフォルダをパスに追加する
'SET RUBY_BIN=%CD% 相当の処理
path_to_add = fso.getParentFolderName(WScript.ScriptFullName)

' たちあげたプロンプトにだけ一時的に追加したいのでEnvironment("Process")にしておく。
' SET PATH=%RUBY_BIN%;%PATH%相当の処理
set env = shell.Environment("Process")
env.Item("PATH") =  path_to_add & ";" & env.item("PATH")

' cmd.exeを実行する
' ruby.exe -v相当の処理
shell.Run "cmd.exe /K ruby.exe -v", ,FALSE

setrbvars.vbsをruby.exeと同じフォルダにおいてダブルクリックするとコマンドプロンプトが立ち上がります。

setrbvars.batは、C:\Windows\System32\cmd.exe /E:ON /K C:\Ruby22-x64\bin\setrbvars.batのようにcmd.exe上で実行されます。
setrbvars.vbsは、WScript.exe もしくは CScript.exeで実行され、cmd.exeを子プロセスとして生成するという違いがあります。

応用例2

setrbvars.rb
require "win32ole"
shell = WIN32OLE.new("WScript.Shell")
env   = shell.Environment("Process")
env.setproperty("item", "PATH", File.expand_path(File.dirname(__FILE__)).gsub("/", "\\\\") + ";" + env.item("PATH"))
shell.Run("cmd.exe /K ruby.exe -v",nil,false)

ダブルクリックでrbを実行できるようになってたら、これをクリックするだけで「Ruby コマンドプロンプトを開く」と同じようにコマンドプロンプトが起動します。

使い方

追記予定
cmd_after_addpath.vbsのショートカットをコマンドプロンプトのカレントフォルダにしたいフォルダ作成して、
作業フォルダ欄を空欄にするとか・・・アイコンを変更するとか・・・Anaconda Promptの起動について調べる - Qiitaに関連したことを書く予定

備考

もともとは、bat-->vbscript-->batみたいな感じで一時的な環境変数をやりとりしようとしてました
"bat プロセス間 環境変数 引継ぎ 共有"でぐぐったら、

batファイル内での環境変数の共有について

PATIO 2008/03/25(火) 10:34:14
確か実行ファイルの環境変数は起動した環境の環境変数のコピーだったと思います。
なので実行ファイルの環境変数を変更しても起動した環境の環境変数は変えられないはずです。
結論として環境変数でデータを返す事はできない。

とのことで、Environment("System"), Environment("User"), Environment("Volatile")のように「一時的じゃないもの」を使わないと引き継げないようでした。
やりたいことは、「たちあげたプロンプトにだけ一時的に追加したい」なので、Environment("Process")と同等のスコープじゃないとちょっと都合が悪い

逆に、

batファイル内での環境変数の共有について

麩 2008/03/25(火) 16:58:44
EXEから呼び出し側Batに戻る事は諦めて、続きの処理をEXEの子プロセスとして生成してしまえば環境変数の引継ぎは出来ませんか?

とのことで、子プロセスはEnvironment("Process")を引き継ぐようだったので、vbscriptからcmd.exeを起動するようにしました。

書いているうちに、「この内容だったら、rubyのwin32oleにもできるだろう」と気がついたので、
[ruby-list 31108] Re WIN32OLE の質問 環境変数の設定はどうやる?を参考にやりました。

参考

[ruby-list 31108] Re WIN32OLE の質問 環境変数の設定はどうやる?
Anaconda Promptの起動について調べる - Qiita
batファイル内での環境変数の共有について – らららのエンジニアラウンジ
Cmd - DOS コマンド一覧 - Programming Field
全ては時の中に… 【VBScript】環境変数の登録
MS Windows_VBScript - PukiWiki
@IT:Windows TIPS -- Tips:WSHで環境変数を設定する
Tech TIPS:setxで環境変数の値を設定する(基本編) - @IT
一時的に環境変数を設定してプログラムを起動するJScript PuppyLinuxで爆速PCライフ
一時的に環境変数 XYZZYHOME を設定してから xyzzy を起動させる - Cookie & Ice cream
Environment プロパティ