「サーバサイドJSのまとめ」ちょっぴり更新。2009年12月01日 03時45分32秒

ふと、ここしばらくのブックマークを見返してたら、ちょっとサーバサイドJSネタがたまってたので少しだけ更新してみました。

今日のところはEJScriptnarwhalの追加とAJAJAがリンク切れになってたのでその修正だけですが、11月に3つくらいSSJSなやつがあったので、後日それらも追加する予定です。多分。

そういやEJScriptは、5月くらいに少しいじった記憶が無きにしも非ずなんだけど、なにやったか覚えてないや。

spam削除支援のGMスクリプトが動かなくなった件2009年09月04日 02時35分04秒

アサブロ管理画面の話なんだけども、結構前のエントリで「コメントやトラバにspam指定してから一定期間が経過してたら削除のチェックをかってに入れる」グリモンスクリプトてのを掲載した。

で、それからずーっと役に立ってたんだけど、今日ふと気がついたらとっくに期間が過ぎてるのに、まったく削除チェックされる気配が見受けられない状態になってた。

そういや今月のはじめに、管理画面に機能が追加されてたので、「HTMLの構造でも変わったかな?」とか思ってFirebugで見てみたんだけど、input[@type="checkbox" and @name="delmsg"] ってのは変わってない。一瞬「Firefoxを3.5にしたのが原因?」みたいなこと考えたんだけども3.5にしてからも動いてたハズなので、この推察も違うと。

document.getElementsByTagName("input") で列挙した要素をFirebugのコンソールに出力してみたら、なぜかチェックボックスが1件も引っかからない。はて。

で、よくよく考えたら、@name="delmsg" は必ず削除用チェックボックスだったことに思い当たって、以前のスクリプトで

// チェックボックスのリスト
var list = document.getElementsByTagName("input");
ってしてたところを
var list = document.getElementsByName("delmsg");
に変更したら、やっとまともに動いた。ちなみに以前のコードでは、前出のコードでinput要素全部列挙してからわざわざ typeとname属性チェックして処理するかどうかを判断してた。最初からgetElementsByName()だったらそんな処理いらんのにね

しっかし、なんでgetElementsByTagName("input")で引っかからんようになったんだろか。

evalとTextStream.OpenTextFileのナゾ2009年01月27日 04時12分05秒

久々にスクリプトネタ

ずいぶんと古い記事なんだけど、「主に言語とシステム開発に関して」さんからリンクしていただいたので便乗してWSHネタ。

話題としてはJScriptで外部ライブラリをロードする手法に関してで、おっしゃるとおり

WSF形式にする。  ←これがベスト ※後述
なのは確かなんだけども、サンプルであげられてたTextStreamオブジェクトのエラーについてちょっと気になったので。

eval()は確かにダメだけどセキュリティは関係ないっす

「主に言語とシステム開発に関して」さんでは、こんなサンプルコードをあげられていた。

// evalを使う
var str = "var fso = WScript.CreateObject('Scripting.FileSystemObject');" +
    "fso.CreateTextFile('b.txt');" +
    "var txt = fso.OpenTextFile('b.txt',2);" +
    "txt.WriteLine('hoge');" +
    "txt.Close();"
eval( str ); 


で、これ実行すると確かに「エラー:書き込みできません。」とでるんだけども、これ、セキュリティが原因じゃないっす。

ためしにこんな風に変えてみたり、

var str = "var fso = WScript.CreateObject('Scripting.FileSystemObject');" +
    "var txt = fso.CreateTextFile('b.txt');" +
    "txt.WriteLine('hoge');" +
    "txt.Close();"
eval( str ); 

またはこんな風に変えてみたり
var str = "var fso = WScript.CreateObject('Scripting.FileSystemObject');" +
    "fso.CreateTextFile('b.txt').Close();" +
    "var txt = fso.OpenTextFile('b.txt',2);" +
    "txt.WriteLine('hoge');" +
    "txt.Close();"
eval( str ); 

すると、エラーにならず、意図どおりに書き込める。要するに、「主に言語とシステム開発に関して」さんのサンプルのエラーはCreateTextFileで書き込み権付で開いたストリームを閉じていないので排他がかかってるということではないかと。

だもんで、eval()方式だからといって、ファイルI/Oを扱うライブラリが使えないということはないんです。実際、dara-jはそういうライブラリ作って、eval()方式で読み込んでつかってるし。

まぁ、eval()がダメな2番目の理由が本当に致命的で、関数化できるのはファイル読み込みくらいまでだもんだから、素直にWSF使ったほうが精神衛生上よろしいのは確かなんですが。

で、ナゾが残る、と。

と、ここまで書いてハタと気づいたんだけども、さっぱり理屈がわからないのだが、「// evalを使わない」ほうのサンプルでは、同じようにCreateTextFile()で開いたストリーム放置しててもエラーがでないんですよ、これが。なんで???

まぁ、コールスタックの数によってセキュリティ警告がでたりでなかったりという不可思議な現象もあるJScriptの環境だから、「そんなこともあるのかぁ」と納得しておくことにしようか。つか、そんな内部の挙動を調べるスキルなんかないし。

KomodoでLatin-1撲滅を試みる2008年10月30日 04時16分58秒

KomodoでHTAを書いてみようと思ったわけだが

仕事でちょっとしたツールが必要になったので、久々にHTAを書くことにした。

単純なJSやHTAなんかは大体サクラエディタでしこしこと書くのだが、バッチやら参照ディレクトリやらでちくっと複雑になりそうだったのでKomodoを使ってみることにした。

が、ちと困ったことが。Shift_JISのソースをKomodoで開くとなぜか「Latin-1」として検出されてしまい、こんな具合で表示されるのだ。

Latin-1化けすぎ

ほんとはこうなんだけど。

ほんとはSJIS

開くたび変更するのは面倒くさい

ドキュメントのプロパティでCP932に変更すればちゃんと表示されるんだけども恒久的に覚えてくれるわけじゃないので、ファイルを開くたびにちくちくと設定する必要があり、すごく面倒くさい。

なので、なにか手はないかと思って調べたら、どうやらKomodoのマクロはファイルを開くタイミングで起動することができるらしい。これでなんとかならんか。

で、マクロ書いてみた

先のリンクとかを参考に、こんなマクロを書いてみたわけだが。

if( ! komodo.document ) return;
var doc = komodo.document;
if( doc.encoding.short_encoding_name == "Latin-1" ) {
    try {
        doc.setEncodingFromEncodingName( "CP932" );
    } catch(e) {
        ko.dialogs.alert( e );
    }
}
このマクロをとりあえずはプロジェクトに登録し、プロパティの「Triggers」で「after file open」を設定してみると、Latin-1として検出された場合のみCP932にエンコードを自動的に変更してくれる。あー、これでイライラせずにすむわ。

ちなみにCP932以外に設定したかったり、トリガになるエンコーディングをLatin-1以外にしたかったりしたら、使用したいエンコードのファイルをKomodoで開いて、以下のマクロで調べてみればよいかと。

if( ! komodo.document ) return;
ko.dialogs.alert( komodo.document.encoding.short_encoding_name );

あ、そういやマクロ中で使用している komodo オブジェクトは使用が推奨されていないそうな。なのでKomodoのバージョンがあがったら動かなくなる可能性なきにしもあらず。まぁ気にしない。

そういや、これToolboxに登録しても検出してくれるのかな?

.wmiコマンドの説明2008年10月21日 04時42分51秒

昨日の続きで、.wmiコマンドの説明でもしようかと。

起動

jsi.js環境でWQLを直接実行するための追加ドットコマンドで、jsi.jsのプロンプトから「.wmi」と入力することで起動します。

昨日の記事でも例示していますが、.wmiを起動すると、モードが通常のJSモードからWQLモードに切り替わり、プロンプト表示も変化します。

Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

jsi > .wmi

WMI Console for jsi.js
server: localhost, root: root/cimv2

wmi@localhost >

.wmiコマンドには、接続パラメータを指定することもできます。指定したパラメータはWbemScripting.SWbemLocatorオブジェクトのConnectServerメソッドの第一~第四引数にそのままそのまま渡されます。具体的には以下の通り。

  1. strServer
    → ログインするコンピュータの名前を指定します。省略時は「.」、すなわちローカルホストになります。
  2. strNamespace
    → ログインする名前空間を指定します。本来は省略も可能ですが、パラメータ展開の都合で第三パラメータ以降の指定が必要な場合は省略できません。その場合はシステム標準の名前空間「root/cimv2」を指定してください。
  3. strUser
    → strServer, strNamespaceで指定されたコンピュータ・名前空間へログインするためのユーザ名を指定します。省略時は現在のセキュリティコンテキストで使用されているログイン名が使用されます。
  4. strPassword
    → strServer, strNamespaceで指定されたコンピュータ・名前空間へログインするためのパスワードを指定します。省略時は現在のセキュリティコンテキストで使用されているログインパスワードが使用されます。

リモートコンピュータ「myserver」の名前空間「root/cimv2」へアカウント「username:password」で接続するには以下のように指定します。

jsi > .wmi myserver root/cimv2 username password

WMI Console for jsi.js
server: myserver, root: root/cimv2

wmi@myserver >

WQLの実行

WQLモードでは、後述のドットコマンドを除いて、WQL以外のコマンドは実行できません。

入力方法はJSモードと同様セミコロンが出現するまでは入力モードです。末尾にセミコロンを入力することで初めてWQLによる検索を実行します。

wmi@localhost > select name, creationdate from win32_process;
// 検索結果がダンプされる
出力はデフォルトではJSON形式ですが、後述のドットコマンド「.format」でカンマ区切りまたはタブ区切りのテキストへ変更することもできます。

また、標準ではコンソールへのみ出力されますが、後述のドットコマンド「.output」でファイルへの出力も指定できます。

WQLモードを終了する場合はドットコマンド「.quit」を入力します。.quitを実行するとJSモードへ戻ります。

wmi@localhost > .quit

jsi >

ドットコマンド「.format」

ドットコマンド「.format」で出力フォーマットの確認・変更が行えます。

パラメータを指定せずに.formatを実行した場合は現在の出力フォーマットが表示されます。

wmi@localhost > .format
 - json-format

wmi@localhost >
パラメータ指定を行う場合は".format"に続けて演算子"="と有効なフォーマット名を指定します。
wmi@localhost > .format = json
 - json-format

wmi@localhost > .format = csv
 - csv-format

wmi@localhost >

.formatで指定可能なフォーマット名は以下の3種類です。

  1. "json"
    → JSON形式で出力します。ただし、1行分のデータのみが正しいJSON形式で、複数データがヒットした場合でも各データ間はカンマで区切られないので注意してください(表示のみなら特に問題なし)。
  2. "csv"
    → CSV(カンマ区切りテキスト)形式で出力します。先頭行はカラムヘッダ、それ以降の行に結果がカンマ区切りで出力されます。
  3. "tsv"
    → TSV(タブ区切りテキスト)形式で出力します。CSVフォーマット同様、先頭行がカラムヘッダ、それ以降が結果データになります。
また、.format =の後に何も入力せずに確定させると、デフォルトのJSONフォーマットに変更されます。

ドットコマンド「.output」

ドットコマンド「.output」を使用することで、検索結果が出力されるストリームを確認・構成することができます。

現在の出力ストリーム構成を確認するには、パラメータ指定なしで「.out」または「.output」と入力します。

wmi@localhost > .out
 - [0]: (standard output stream)

wmi@localhost >

ストリームの追加

デフォルトの状態では標準出力のみがストリームとして登録された状態です。以下のように、「+=」を使用してファイルストリームを追加することができます。

wmi@localhost > .out += log.txt
 - [0]: (standard output stream)
 - [1]: file stream:[log.txt]

wmi@localhost >
ファイルのパスはjsi.jsのインストールディレクトリからの相対パスまたは絶対パスで指定できます。絶対パス指定する場合は、パスを二重引用符で括らないでください

上記の構成では、標準出力および.jsi.jsのインストールディレクトリ直下のlog.txtに結果が出力されます。

ストリームの削除

追加したストリームを構成から削除するには「-=」に続けてファイル名/パスを入力してください。

wmi@localhost > .out
 - [0]: (standard output stream)
 - [1]: file stream:[log.txt]

wmi@localhost > .out -= log.txt
 - [0]: (standard output stream)

wmi@localhost >

現在のバージョンではまれにストリームが削除できなくなる場合があります。いずれ修正予定ですが、このような状態になったらいったんjsi.jsを終了してください。

まとめ

というように、WQLを実行して結果を表示するだけのコマンドで、検索結果に対してなにか処理できるわけでもないので実用性はあまりありません。

ま、リモート接続ができるので、たとえばCSVフォーマットでリモートコンピュータにインストールされているプリンタを列挙したりとか、多少は役に立つかもしれませんが、WMIのクラスリファレンス見ながら「へぇ、こんなクラスあるのかー。どんな情報取れるんだろ」を試すくらいしか使い道ないかもしれません。

またしても長めの記事になっちゃったので、ライブラリ自体の説明はまた後日。