読者です 読者をやめる 読者になる 読者になる

スベリミナル効果

技術的なことを書こうと思ってたけど何でも書くことにします

技術的なことを書きたいんですけどね… 指摘・質問・罵倒コメントください…
ダジャレ好きの方はこちらにどうぞ→スベリブログ2.0

WindowsのルーティングをJavaScript(JScript)で半自動設定する

.emacs を掘り下げようと思っていたんですが、
表題の件の方が優先度高かったのでその話を。経緯としては以下の感じ。

<要件>

  • NICが3つあって、ケースによってルーティングを設定したい
  • > route add 0.0.0.0 mask 0.0.0.0 10.0.0.253 metric 10
    みたいのを追加削除したい
  • 上のコマンド叩くときはDHCPで割り当てられてる動的IPを拾ってくる必要あり
<ことの経緯>
  1. 今まではActivePerl 入れてPerlで書いてた
  2. 会社PC入れ替え(XP→7)を機に、ActivePerl なしでも書けないかを検討
  3. Windowsのバッチで書けないの?→キツイ
  4. WSH(Windows Script Host) というスクリプト実行環境がある
    というか、ActivePerlもこの仕組み使ってるらしい
    標準でVBScriptJScript(まあ、JavaScriptと思ってよい...)が使える
  5. Windows PowerShellWSHの後継でMicrosoft的にはこっち推奨のよう→知るか
  6. JavaScript勉強したいと思ってたから丁度良い、WSH + JScriptで書こう!
  7. んじゃ実装しつつ、もうちょっと細かく調べっか ←いまここ

で、そもそもJavaScriptも含めてバージョンとかちゃんと理解してない部分があったので、
いっちょやってみっか!的なノリで調べてみました。

  • JavaScript, JScriptはどちらもECMAScript(エクマスクリプト)の方言
  • とは言いつつ、"JavaScript"って言ったらその方言も含めて全部指すことが多い
  • ECMAScriptってのは、1996年ごろにブラウザごとでバラバラ実装だった
    JavaScript達をどげんかせんといかん、ってことで標準化されたスクリプト言語
  • 現在出回ってるJavaScriptECMAScriptのEdition3か5に準拠してると思って良い、多分
  • WindowsJScriptのバージョンは下記を見れば分かる
    C:\Windows\System32\jscript.dll を右クリック>プロパティ>詳細タブ>バージョン情報を確認
    ファイルバージョンが5.8.xxxとかならばJScript5.8→これはECMAScript Editon3に準拠している(純正Javascriptの1.5に相当)
  • Webの実装だと、ブラウザごとに若干の違いがあるようです
  • というようなことは、Wikipedia見ればほぼ載ってますよ
    ECMAScript, JavaScript, JScript
まとめると、ECMAクマヤコン、ECMAクマヤコン、標準化されたJavaScriptになれ〜
ってことですね。(ちがうよ、ぜんぜんちがうよ、1スベリ)


ただ、今回の目的においてはここまで調べる必要は無かったですね、、、

一応、最近買った 『Effective JavaScript』の冒頭の指示
「どのJavaScriptを使っているのかを意識しよう」に従ったのです。

"use strict";

などのECMAScript Edition5から使える記述は、
僕のVistaん(書いてる途中で7にしたけど)では使えないということが分かりました。


にしてもこれだけで時間かかった、、、

JavaScriptを、ブログを書くのを邪魔するリストに入れておこうと思います。(2スベリ)



実装はまた次更新、、、と言ってたら2週間過ぎてた、、、遅すぎや!
とりあえずはっつける、、、

function IPConfig () {
    this.net1_ip;
    this.net2_ip;

    var objShell = WScript.CreateObject("WScript.Shell")
    var objExec  = objShell.Exec("cmd /c ipconfig")

    while (!objExec.StdOut.AtEndOfStream) {
	if (objExec.StdOut.ReadLine().match(/IPv4[^:]+:\s*(\d+\.\d+\.\d+\.\d+)/)) {
	    var ip = RegExp.$1;
	    if (ip.match(/192\.168\.1\./)) {
		this.net1_ip = ip;
	    }
	    else if (ip.match(/10\.0\.0\./)) {
		this.net2_ip = ip;
	    }
	}
    }
}


function CmdExec (cmd) {
    var objShell = WScript.CreateObject("WScript.Shell")
    var objExec  = objShell.Exec(cmd)

    while (objExec.Status == 0) {
	WScript.Sleep(100);
    }

    WScript.Echo("retcode: "+ objExec.ExitCode);
    if (objExec.ExitCode == 0) {
	WScript.Echo("SUCCESS: "+ cmd);
	while(!objExec.StdErr.AtEndOfStream) {
	    WScript.Echo("  WARN:"+ objExec.StdErr.ReadLine());
	}
    } else {
	WScript.Echo("FAILED:"+ cmd);
	while(!objExec.StdErr.AtEndOfStream) {
	    WScript.Echo(" ERROR:"+ objExec.StdErr.ReadLine());
	}
    }
}


/* ****** routing info ****** */
var net2_rt = new Array(
    ["10.0.0.0", "255.255.0.0"],
    ["172.27.0.0", "255.255.0.0"],
    ["172.22.0.0", "255.255.0.0"],
    ["172.23.100.0", "255.255.255.0"],
    []
)

var net1_rt = new Array(
    ["192.168.100.0", "255.255.255.0", "192.168.1.253", 1],
    ["21.21.21.21", "255.255.255.255", "192.168.1.253", 1],
    ["123.123.123.123", "255.255.255.255", "192.168.1.253", 1],
    []
)
/* ***************************************** */

ipconfig = new IPConfig;

while (1) {
    WScript.Echo("")
    WScript.Echo("Usage: [Mode] [Option]...")
    WScript.Echo("")
    WScript.Echo("Input Mode:")
    WScript.Echo("      net1 [1] ... set net1 routing")
    WScript.Echo("      net2 [2] ... set net2 routing")
    WScript.Echo("")
    WScript.Echo("   confirm [c] ... display the result of 'route print'")
    WScript.Echo("")
    WScript.Echo("Option:")
    WScript.Echo("	del ... delete")

    var input = WScript.StdIn.ReadLine();
    if (input.match(/^(\w*)\s*(\w*)$/)) {
	var mode   = RegExp.$1;
	var option = RegExp.$2;
    }
    var method = "add"
    if (option == "del" || mode == "del") { method = "delete"; }

    // net2
    if (mode == "net2" || mode == "2") {
	if (ipconfig.net2_ip != null && ipconfig.net2_ip != "") {
	    for (var i = 0; i < net2_rt.length; i++) {
		if (net2_rt[i].length == 0) { break; }
		CmdExec("route " + method + " " + net2_rt[i][0] + " mask " + net2_rt[i][1] + " " + "202.221.115.1");
	    }
	} else {
	    WScript.Echo("[ERROR] didn't find net2 ip...")
	}
    }
    // net1
    else if (mode == "net1" || mode == "1") {
	if (ipconfig.net1_ip != null && ipconfig.net1_ip != "") {
	    for (var i = 0; i < net1_rt.length; i++) {
		if (net1_rt[i].length == 0) { break; }
		CmdExec("route " + method + " " + net1_rt[i][0] + " mask " + net1_rt[i][1] + " " + net1_rt[i][2]);
	    }
	} else {
	    WScript.Echo("[ERROR] didn't find net1 ip...")
	}
    }
    // show routing
    else if (mode == "confirm" || mode == "c") {
	var objShell = WScript.CreateObject("WScript.Shell")
    	var objExec  = objShell.Exec("cmd /c route print -4")
	while (!objExec.StdOut.AtEndOfStream) {
	    WScript.Echo(objExec.StdOut.ReadLine())
	}
    }

    WScript.Echo("")
    WScript.Echo("input 'enter' to end")
    WScript.Echo("If you want to do anymore, input [r]")
    var input2 = WScript.StdIn.ReadLine();
    if (input2 != "r") {
	break
    }
}

特定IPを隠そうとして色々削ってたらちょっとニュアンスが変わってしまいましたが、、、

で、こいつを下記batで起動させます。

cscript C:\Users\hoge\Settings\routing_cmd\set_routing.js //Nologo

Windows Vista, 7 ではルーティング設定に管理者権限がいるので、
このbatへのショートカットを作成し、以下を設定します。

右クリック>プロパティ>詳細設定>管理者として実行にチェック

これでめでたく設定コマンドが動きます、多分、、、
実行してからコマンド打ちます。

net1 と打てばそのルーティングが書かれ、
net1 del と打てば消える、
r 押して c を押せば確認できる、程度の簡単な物です。
実際はもう少しオプションあるんですが、都合上消してます。


なんか、Perlのクセで無駄なセミコロンとかあったり、
全然オブジェクティブじゃなかったりしますが、、、その程度の実力です、はい。

細かい文法とかは、、、まあ、ググってください(おい



ということで、ルーティングのスクリプトで、多少の
ルーティン グ(が)解消されたということで、、、(3スベリ)