需要がなさそうなTCP/IP設定切り替えスクリプト ― 2007年12月23日 03時31分41秒
netshコマンド
えー、久々のWSHネタで、需要が少なそうなスクリプト。Win2KとかXPとかでネットワーク設定を構成する「netsh」ってコマンドがあるんだけども、これが設定のダンプやリストアができるので、ちょこちょこっとTCP/IPの設定切り替えたりするのに割と便利。
例えば「netsh interface dump」ってコマンドラインから実行すると、こんな感じで表示される。
C:\Documents and Settings\dara-j>netsh interface dump #======================== # インターフェイス構成 #======================== pushd interface reset all popd # インターフェイス構成の最後 # ---------------------------------- # インターフェイス IP 構成 # ---------------------------------- pushd interface ip # "ローカル エリア接続" のインターフェイス IP 構成 set address name = "ローカル エリア接続" source = dhcp set dns name = "ローカル エリア接続" source = dhcp set wins name = "ローカル エリア接続" source = dhcp popd # インターフェイス IP 構成の最後 C:\Documents and Settings\dara-j>この例はシンプルなDHCP設定の状態を示している。手動でIP設定をしていると、こんな感じ。(IP構成の部分のみの抜粋)
# ---------------------------------- # インターフェイス IP 構成 # ---------------------------------- pushd interface ip # "ローカル エリア接続" のインターフェイス IP 構成 set address name = "ローカル エリア接続" source = static addr = 192.168.0.100 ma sk = 255.255.255.0 set address name = "ローカル エリア接続" gateway = 192.168.0.1 gwmetric = 2 set dns name = "ローカル エリア接続" source = static addr = 192.168.0.1 set wins name = "ローカル エリア接続" source = static addr = none
んで、この一連の出力は、netshでネットワーク構成を行うバッチコマンドになっているので、これをテキストファイルに保存しておいて、「netsh exec ファイル名」なんてすると、構成をリストアできる。
わざわざスクリプトを作成してみる
これだけでも十分実用的なのだが、最近3~4種類のIP設定を頻繁に切り替える需要がdara-j的に発生したので、いちいちファイル名をタイプするのが面倒くさくなってきたのでスクリプトを書いてみた。
var shell = new ActiveXObject("WScript.Shell"); var fso = new ActiveXObject("Scripting.FileSystemObject"); if( /wscript\.exe$/i.test( WSH.FullName ) ) { shell.Run( [ "cscript //nologlo", "\"" + WSH.ScriptFullName + "\"" ].join(" ") ); WSH.Quit(); } Object.extend = function(dest, src) { for(var key in src) { dest[key] = src[key]; } return dest; } var $continue = {}; var $break = {}; var Enumerable = { each : function(iterator) { var index = 0; try { this._each( function(value) { try { iterator( value, index++ ); } catch(e) { if( e != $continue ) throw e; } } ); } catch(e) { if( e != $break ) throw e; } }, map : function(iterator) { var result = []; this.each( function(item, index) { result.push( iterator(item, index) ); } ); return result; }, findAll : function(iterator) { var result = []; this.each( function(item, index) { if( iterator(item, index) ) result.push( item ); } ); return result; }, find : function(iterator) { var result = null; this.each( function(item, index) { var r = iterator( item, index ); if( r ) { result = item; throw $break; } } ); return result; }, toArray : function() { var result = []; this.each(function(item) { result.push( item ); } ); return result; } }; Object.extend( Array.prototype, Enumerable ); Array.prototype._each = function(iterator) { for(var i = 0; i < this.length; i++) { iterator( this[i] ); } }; Object.extend( Enumerator.prototype, Enumerable ); Enumerator.prototype._each = function(iterator) { for(this.moveFirst(); ! this.atEnd(); this.moveNext()) { iterator( this.item() ); } }; var console = { echo : function(msg) { if( msg == null ) msg = ""; if( msg instanceof Array ) { msg.each( function(item) { console.echo( item ); } ); return; } WSH.StdOut.WriteLine( String(msg) ); }, print : function(msg) { if( msg == null ) msg = ""; if( msg instanceof Array ) { msg.each( function(item) { console.print( item ); } ); return; } WSH.StdOut.Write( String(msg) ); }, readLine : function(msg) { if( msg ) console.print( [ msg, " > " ] ); return WSH.StdIn.ReadLine(); }, execute : function(cmd) { var exec = shell.Exec( cmd ); while( exec.Status == 0 ) { WSH.Sleep( 100 ); } console.echo( exec.StdOut.ReadAll() ); } }; Object.extend( this, console ); shell.CurrentDirectory = fso.GetFile( WSH.ScriptFullName ).ParentFolder.Path; var targets = new Enumerator( fso.GetFolder( shell.CurrentDirectory ).Files ).findAll( function(fileInfo) { // 拡張子でフィルタリング return /\.netsh$/i.test( fileInfo.Name ); } ); while( true ) { echo( [ "適用する設定を選択してください。(0 で終了)", "----", targets.map( function(item, index) { return ( index + 1 ) + " : " + item.Name; } ) ] ); var n = parseInt( readLine( " " ) ); if( n == 0 ) break; if( n < 1 || n > targets.length ) continue; execute( [ "netsh", "exec", "\"" + targets[n - 1].Path + "\"" ].join(" ") ); execute( "ipconfig /all" ); break; };ちょっと長いのだが、FSOのループ処理用にEnumeratorを拡張するためだけにprototype.jsのeach系メソッドやObject.extendの定義をしているので、単純ループに置き換えて短くすることもできる。
んで、なにやってるかっていうと、
- カレントディレクトリの特定の拡張子(ここでは.netshとかでっち上げてる)のファイルを列挙
- 列挙されたファイルを番号入力で選択
- 選択されたファイルを引数にして「netsh exec」を実行する
環境構築
まず、IP設定をダンプする。保存したい構成の時に「netsh interface dump > ファイル名」てな要領でダンプ出力をそのままファイルに保存する。
保存したファイルと同じパスに上記スクリプトを設置して、あとはコマンドラインから「cscript スクリプトファイル名」って実行する。またはダブルクリックでもよい。
dara-jはこれをユーザディレクトリ(Documents and Settings\ユーザ名)に直接配置して、さらにスクリプトを実行するバッチファイルも同じ場所に置いている。こうすると環境変数の設定如何にかかわらず、「ファイル名を指定して実行」でcmd.exeを起動してすぐに使える。うん、役立つ場面が少なそうだ。
参考リソース
netshコマンド自体はもっと多彩なことができる(風。あんまよく知らない-_-;)ので、参考になるリンクをいくつか載せておく。
-
Microsoft TechNetの解説ページ
-
ITproの「管理者必見! ネットワーク・コマンド集」より。このエントリよりよっぽど実用的な解説やサンプルあり。
-
Windows TIPSより。「netsh -f ファイル名」なんてのもあるんだ。
最近のコメント