'// Windows Script Host を使い尽くす //

このエントリーをはてなブックマークに追加
皆さんWindows Script Hostは使っていますか?
これあるだけで,簡単なことならチョチョイと出来てしまうと思います.
VBS,JS等で利用できるので,さまざまな利用方法があると思います.
WSHを使い尽くしましょう.
MSDN
http://www.microsoft.com/japan/developer/library/default.asp?URL=/japan/developer/library/script56/wsoriWindowsScriptHost.htm
21:02/01/07 19:45
参考文献

Windows Script Room
http://www2f.biglobe.ne.jp/~takan/javac/js/wsh/
Windows Scripting Host
http://member.nifty.ne.jp/aya/wsh/index.htm
Windows Scripting Host Laboratory
http://www.roy.hi-ho.ne.jp/mutaguchi/wsh/
Windows Script Host メーリングリスト
http://www.users.gr.jp/ml/wsh.asp
Virus情報: VBS.Pleh.A ワーム
http://www.caj.co.jp/tec/tec_n/f_vbspleh.htm
http://pc.2ch.net/test/read.cgi/win/1009175619/
個人的には↑でやって欲しかったり
4あっちの11:02/01/17 00:34
コソーリ書き込む。

>>3
むしろ技術話は、こちらでやって欲しかったり
53:02/01/17 04:28
コソーリ書き込んでるのを発見したので意味のないレスを付けてみる。

>>4
個人的には wsh や bash, tcsh とかはwin板やunix板で…っと思っただけで
別にこっちでやってもらっても構わないのですが、
このままではこのスレ過去ログへ一直線になっちゃいそうな予感(w
64:02/01/17 22:55
>>5
たぶんプログラム板のみなさんからすれば、WSHなんて(以下略)だと
思うので、メインはWin板でやったらいいと思うんですが、
COMとかの純粋な技術話は、むしろプログラム板向けかなあと。
73:02/01/18 01:20
>>6
御意
84=あっちの11:02/02/04 01:33
そういうネタはこっちでやれ!
と思ったのは私だけじゃないはずだぞ。
誘導すべきだったか。スマソ。
94=あっちの11:02/02/04 03:02
Win板の方でWSH(スクリプト)からAPIを呼ぶのは、なぜ良くない(嫌われる)?
って議論があったので、こっちで続けようかと。
1の人には申し訳ないけど、スレ再利用ってことで。
あ、当方プログラマじゃないです。
(VBをかじっただけの日曜プログラマーもどき)
10 :02/02/04 03:07
エム口さん、体に毒だよ。早く寝なさい!
健康が一番です。
114=あっちの11:02/02/04 03:11
>>10
・・・はい・・・。
12sage:02/02/04 13:47
そうそう、M口さんがいてくれないと2chのWSHスレはもたないからね。
体には気をつけなよ。
13デフォルトの名無しさん:02/02/04 13:50
ところで、WSHでおそらく一番利用されているであろうvbscriptは、.NET
ではなくなってしまうのだろうか?MSDNのページにいったら、Jscript.NET
はあるみたいなんだけど…。vbscript.NETみたいなのはないのかな?
14__NMAG__:02/02/04 22:21
個人的には Windows 2000 派なんだけど XP ではかなりコマンドラインツールが強化されたね。
どうしてもバッチ的処理になってしまうがプロキシ切り替えなんて使えそう???
(中編、後編もあるよ)

http://www.atmarkit.co.jp/fwin2k/xp_feature/013commandtool/commandtool.html
1511:02/02/05 15:18
>>12
どうでもいいけど、なんで本名さらされてんだよ俺(w
ここでも11でよろしく。
熱が下がったからちょっとだけ書き込む。

>>13
VBSとVBは統合されてVB.NETになります。
が、ここで言うVBSは、あくまでASP中で動作するVBSの
ことであって、ブラウザやWSHで動作するVBSが今後
どうなるかは、私も情報をつかんでいません。
ぜひ教えてもらいたいです。
1613:02/02/07 01:42
>>15

統合されたVB.NETがそのままWSHなどでフルに使えるとしたら、RADツールとして
VB.NETの価値がなくなってしまうのだろうから、VBS.NETみたいな形のサブセット
言語が開発されるんだろうか?それか、WSH自体なくなってしまうとか?

いずれにしても、VBScriptはわずか4年ちょっとで消えてしまうということなんだね。
18FATGIRL:02/02/26 00:52
使い尽くしたあとには何が残る.....。
私は後悔していません。
だから.....。
>>9
亀ですが、まぁ1つの意見として・・・

えと、WSHの普及に使命を感じてるような人には
目的にそぐわないコンポーネントでバイナリをいじることに
意義を見出したり、
DynaCallでWSHの可能性が広がることに感動を覚えたりして
HPのためのネタさがしにあけるれるのかもしれない。

けど、普通な人は
バッチの延長みたいな感覚でWSHを使ってると思うです。
位置づけ的には、その程度かな?!

例えばWSHでExcelを使うとき、
データを処理するのがPCする目的であって、
WSHをいじるのが目的じゃない
だから目的にあったコンポーネントを使って、
安全に即決にできるのを望む。
それを
ちょっと間違えたらやばいエラーで暴走しかねない
ものを、わざわざ使うのは、
やはりWSHマニアだけだと思うです。
これって間違ってますかね?

ちなみに、自分は使っちゃダメとか思いませんし、
趣味でプログラム組んでる人です。
2011:02/04/04 02:20
>>19
全面的に同意(汗
やっぱり、冷静な第三者の意見は説得力あります。

今度DynaCallの話でもめたら、このレス紹介させていただきやす。
俺はマニアだから使うけど、イパーン人は使わない方がイイよ、って。

どうもスレ汚し申し訳ありませんでした。
(と言ってもこのスレ、ネタがあんまりないんだけど)
M□さんが、むこうのスレでやっている事は、
むしろこっちの板の方が合ってると思うですよ。
ほんとは・・・
使いたければ使えばいいんじゃないの?
ただ、Win標準の機能であることが大きな利点だと思ってるんで、
WSHでAPIコールなんて、まさに趣味の世界だとは思う。

しかし、Win板で絡んできた奴はなぜわざわざあそこに書いたんだろう。
HSPもスクリプトだが、小中学生が平気でAPI呼んでるぞ。(w
23 :02/04/06 22:25
 test
test
24IUnknown:02/04/06 22:27
=====================================
  DynaCall で構造体を扱う件について
=====================================

今日のところは解説する時間が取れないのでコードの掲載に留めます。
動作確認は 98系が Windows ME, NT系が Windows 2000 で行いました。

ポイントとしては構造体のデータに文字列型のデータを利用している
ということです。オートメーションでは BSTR と呼ばれるこのデータ型は
長さ情報を持ったメモリ領域へのポインタであり Null コードでさえも
含めることができます。つまり任意サイズのバイナリデータを格納できるのです。
構造体も引数として渡すときはポインタ渡しなので代用が可能なのです。
以前に「出来そうな気がする」と書いたのはこういう理由からです。

※ JScript や VBScript ではデータ型はすべて VARIANT ではという
疑問を持つ方もいると思いますが、このあたりは DynaCall がうまいこと
やってくれています。

興味のある人はコードを追ってみてください。また下記のサイトなども
参考にされるとよいと思います。


BSTR について

http://www.microsoft.com/japan/developer/library/default.asp?URL=/japan/developer/library/vbcon98/vbconpassingstringstodllprocedure.htm
http://www.microsoft.com/japan/developer/library/dsmsdn/drgui042099.htm


VARIANT について
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/automat/htm_hh2/chap6_7zdz.asp


※ @OwnRisk でお願いします。動作報告などがいただけると助かります。
※ 今後もう少し汎用性を持たせるために拡張を行いますが詳細は後日ということで。。。
25IUnknown:02/04/06 22:32
//------------------------------------------------------------------------------
// Struct クラスの定義
//------------------------------------------------------------------------------

  // コンストラクタ
    function Struct() {
        var i, args;
        i = Math.floor(arguments[0] / 2) + 1;
        args = new Array(i);
        this.value  = args.join("\0");
        this.length = this.value.length * 2;
    }

  // byteCodeAt() メソッドの定義
    Struct.prototype.byteCodeAt = function(idx, len) {
        var i, j, w1, w2, t, a, b;
        i = Math.round((idx - 1) / 2);
        j = idx % 2;
        w1 = this.value.charCodeAt(i);

      // バイトコードの取得
        t = typeof(len);
        if ((t == "number") || (t == "undefined")) {
            switch (len) {
              case undefined:
              case 1:
                return(w1.w2b(j));
              case 2:
                return(w1);
              case 4:
                w2 = this.value.charCodeAt(i + 1);
                return(w1 + (w2 << 16));
              default:
                return(null);
            }
        }

      // バイナリダンプ
        if (t == "string") {
            a = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F");
            b = w1.w2b(j);
            return(len + a[Math.floor(b / 16)] + a[b % 16]);
        }
        
    }

26IUnknown:02/04/06 22:34
//------------------------------------------------------------------------------
// Number クラスの定義追加
//------------------------------------------------------------------------------

  // dw2w() メソッドの定義 [ DWORD -> WORD(2) ]
    Number.prototype.dw2w = function(i) {
        switch (i) {
            case 0:
                return(this & 0xFFFF);
            case 1:
                return(this >>> 16);
            default:
                return(null);
        }
    }

  // w2b() メソッドの定義 [ WORD -> BYTE(2) ]
    Number.prototype.w2b = function(i) {
        switch (i) {
            case 0:
                return(this & 0x00FF);
            case 1:
                return(this >>> 8);
            default:
                return(null);
        }
    }
27IUnknown:02/04/06 22:35
//------------------------------------------------------------------------------
// カーソル座標の取得
//------------------------------------------------------------------------------

    var point = new Struct(8);

    var UserWrap = new ActiveXObject("DynamicWrapper");
    UserWrap.Register("user32.dll", "GetCursorPos", "i=w",  "f=s", "r=l");

    WScript.Echo("ボタンを押してから 2秒後にカーソル座標を取得します。");
    WScript.Sleep(2000);
    UserWrap.GetCursorPos(point.value);

  // POINT 構造体のダンプ
    var a = new Array();
    for (i=0; i<point.length; i++) {
        a.push(point.byteCodeAt(i, ""));
    }

  // 結果の表示
    WScript.Echo([
        "X座標: " + point.byteCodeAt(0, 4),
        "Y座標: " + point.byteCodeAt(4, 4),
        "",
        "POINT 構造体: ",
        a.join(" ")
    ].join("\n"));
28IUnknown:02/04/06 22:37
取り敢えず、三つを順に繋げて hogehoge.js とした後、
wscript.exe で実行してみてください。
2911:02/04/07 13:43
>>21
いやいや、プログラミングを生業としている方々に、WSHを紹介する
必要性は皆無と思われます。
むしろ、プログラミングなんかやったことね-ぜ、という方々に、
ちょっとやってみませんか、メモ帳があればできますよ、ということを
伝えたいという意図があり、それを実現するのはやっぱWin板がいいんです。

>>24-28
Win2000+IE6+WSH5.6の環境で動作しました。
何度見てもやっぱり、ほえー、という感想しかないです。
内容は、あんまり理解できませんです(汗
>>22さんが言うとおり、これは間違いなく趣味の世界だな。
microsoft.public.scripting.wshに投稿したら、英雄扱いされるかもね(w

wsc化して、汎用コードにできませんかねえ?
そうすれば、多少は実用性も出てくるんじゃないかと。
30IUnknown:02/04/07 21:58
>11
どの程度、需要があるかはわかりませんが、スクリプトも少しずつ大きくなって
行きそうなので下記にアップすることにします。

http://members.tripod.co.jp/IUnknown/WSH/DynaCall/sample.js

前述のサンプルコードでは構造体の受け取りしか出来ませんが、今回のは
任意データの構造体を作成できるように拡張してます。今のところ、16進数で
1バイト、2バイト、4バイトの指定しか認識しません。このあたりはもう少し拡張の
アイデアがあるので少しずつ試していこうと思っています。


>wsc化して、汎用コードにできませんかねえ?
もう少し仕様が固まってきたら Windows スクリプト コンポーネントと
Windows スクリプト ファイル (*.wsf) の形態で公開しようと思います。


<ちょっとだけ補足>
今回のコードには JScript を使っていますがそれには理由があります。
構造体の作成には BSTR が保持するメモリ領域へ直接バイトコードを
書き込めないといけません。JScript では String オブジェクトに fromCharCode()
メソッドが用意されています。これは Unicode 文字列のコードを指定して
文字列を作成するというメソッドであり、つまりは 2バイト単位のコードで
BSTR を作成していくことが出来るのです。VBScript にはこれにあたる
機能を見つけることが出来ませんでした。もともとこれらのスクリプトエンジンは
ユーザ側からは ANSI 文字列(ShiftJIS)で扱い、内部で暗黙的な Unicode への
変換が行われますが fromCharCode() と CharCodeAt() のメソッドは
この垣根を越えて直接バイトコードでのアクセスを許してくれるということで
これらメソッドが無ければ標準機能で構造体を扱うのは無理だったかも知れません。

あなた方のやってることは、紛れもなくすごいことです。
WSH とか関係なく。
32向こうの???番:02/04/08 10:33
だから〜まだやるのね〜
API呼ぶだけじゃなくて構造体まで〜
別に標準の機能で出来るんだったら簡単なことなんじゃないの?
つーか、そこまでしてスクリプト言語に拘って
何の意味があんの???ホント気になるよ
WScript.Echoで文字列を複数行表示するときの書き方がナンカイイ
これって遅くなったりしないのかなア(俺も他はよくわからんです(w
34IUnknown:02/04/08 23:33
35IUnknown:02/04/09 00:15
VBScript でもバイトコードの読み書きが出来ますね。
結構盲点でした。

AscB, ChrB, MidB, LenB, AscW, ChrW, String 辺りの関数を
使えば同様の処理が記述出来そうです。
>>29
>wsc化して、汎用コードにできませんかねえ?
>そうすれば、多少は実用性も出てくるんじゃないかと。

「汎用」とか「実用」なんて言葉は、使わない方がいいと思われ。
「知的好奇心を満たすため」ということにしといた方がいいですよ。
3711:02/04/09 01:36
>>32
はい、ここまでくると、さすがに趣味以外の何物でもございません。
ま、こんな実用的ではないネタで楽しんでる漏れらなんか、ほっといた方がいいですよ。

>>33
JSってそう書くと、配列のオブジェクトになるんだなあ。VBSじゃこういう真似はできない。
せいぜい、
Join(Array("一行目", _
"二行目", _
"三行目", _
"四行目"),vbCrLf)
くらいのものか。

>>35
言おうと思ったら先を越されて残念。実際、VBSで作ったら、かなり
藁えるコードになると思うけど。

>>36
いやいや、わずか数十KBのDLLとWindows標準機能だけで、構造体を引数に
取るAPI関数を呼び出す汎用的コンポーネントが作れる、ということが、
私の知的好奇心を満たすのであります。
>>26
dw2w() と w2b() の
return(this >>> 16) と return(this >>> 8)
が気になった。
そんで、気が付いたんだけど、
除算なんかで整数化したい時、ビット演算が有効。
いちいちMathの奴呼ばなくてもすむ。
Math.floor(b/16) → b>>4

>>33
WScript.Echo の引数が SAFEARRAYだから
都合よくまとめてくれるんだね>JS

>>37
どうでもいいけど、引数に渡すのは構造体じゃなくて
そのポインタだ
3938:02/04/09 05:43
そういやぁ
WScript.Echo(0,1,2,3,"4\n",5,6,7,8,9,10,11,12,13,14,15);
って出来るんだった・・・
VBS厨もこれ使え
プログラムの内容はともあれ、JavaScript(JScript?)では
最近、久し振りに見た珠玉のコードだね。細かいところに
そのセンスが見え隠れしている。
41IUnknown:02/04/10 00:36
>32, 36
これはグローバルな意見の代表的なものですね。そりゃあ、私だって
選択肢が複数ある場合にはベストなものを選びなさいって言います
からね。API 等を扱う必然性が発生したときに JScript with DynaCall
を勧めることは無いですよ。この辺りは 11 さんが代弁してくれて
いますし、これ以上の意見はありませんが、今回の件で言えば、このスレ
自体が "趣味と好奇心" というローカルなスコープで議論されていると
思うんですよ。そういう意味では "汎用性" や "実用性" という表現も
ありかなと。それともいっそのこと "趣味::汎用性" とか "好奇心::実用性"
とか書きましょうか?(いや冗談です)ですから私や 11 さんの発言は
ローカルスコープで捉えていただければと思います。私たちだって
グローバルな意見は皆さんと同じなんですから...。


>33, 40
実は私は JScript や VBScript が特別得意というわけではないです。
ただあちこちの言語を齧っているので、そのおいしい部分を "手法" と
いう形で盛り込んでみただけです。ですから見る人が見れば「当たり前」
ということになってしまうでしょうね。これはビット演算然り、join("\n")
による文字列結合然りです。ただそうでない人たちが面白いと感じて
くれるのであれば、公開した甲斐があったかなと思います。


>32
>>別に標準の機能で出来るんだったら簡単なことなんじゃないの?
(1) BSTR がバイナリデータを格納できるデータ型であること。
(2) JScript にはバイトコードで文字列の作成や読み込みが
    可能なメソッドが提供されていること。

この二点にさえ気付けばそれほど難しいことではないのかも知れませんね。
例えばそれを象徴する例として以下のコードを挙げておきます。
汎用性は皆無ですがちゃんとマウスの座標が取得できます。

  // 8バイトの BSTR 作成 (2バイト x 4文字)
    var point = "hoge";        // 何でもいいんです、4文字(以上)であれば...

    var UserWrap = new ActiveXObject("DynamicWrapper");
    UserWrap.Register("user32.dll", "GetCursorPos", "i=w",  "f=s", "r=l");

    WScript.Echo("ボタンを押してから 2秒後にカーソル座標を取得します。");
    WScript.Sleep(2000);
    UserWrap.GetCursorPos(point);

  // 結果の表示
    WScript.Echo([
        "X座標: " + point.charCodeAt(0),
        "Y座標: " + point.charCodeAt(2),
    ].join("\n"));
42IUnknown:02/04/10 00:37
>11
>>言おうと思ったら先を越されて残念。実際、VBSで作ったら、かなり
>>藁えるコードになると思うけど。
私の方も「11さんのことだからもう気付いているだろうな」と思いながら
書き込んでたりしました...。あと関数呼び出しの VBScript では
コードがかなり見難くなってしまうでしょうね。とはいえクラスの定義や
メソッド、プロパティの定義もちゃんと機能が用意されているので
多分実現は可能でしょう(クラス化は必須ではありませんけど)。


>38
2の階乗の除算で商を求めるときに有効ということですね。
ム板ならではのレス感謝。ということで測定!

    n = 500000;

  // Math.floor() の場合
    d1 = new Date();
    for (i=0; i<n; i++) {
        Math.floor(i / 2);
//        i % 2;
    }
    d2 = new Date();

  // >> 演算子の場合
    d3 = new Date();
    for (i=0; i<n; i++) {
        i >> 1;
//        i & 1;
    }
    d4 = new Date();

    a = d2.getTime() - d1.getTime();
    b = d4.getTime() - d3.getTime();
    c = ((b / a) * 100).toString();
    WScript.Echo([
        a,
        b,
        c.match(/.*\.[0-9]{2}/) + "%"
    ].join("\n"));

約1/2ですね。今回はコンストラクタ関数内で1度呼ばれるだけなので
処理速度に影響はないですが、反復処理内では徐々に効いてきそうですね。
ちなみにコードがスマートになるので早速使わせていただきました。

ついでに測定した 2の剰余では % より & の方が若干高速でした。
(コメント部を入れ替えて下さい)。
43IUnknown:02/04/10 00:37
>33
高速化の話が出たついでに...

私が好んで使う join() ですが文字列の結合時に威力を発揮します。
n が大きいほどその効果も絶大となります。

    n = 100000;

// += を使った場合
    d1 = new Date();
    var s = new String;
    for (i=0; i<n; i++) s += "1234";
    d2 = new Date();

// join() を使った場合
    d3 = new Date();
    var a = new Array();
    for (i=0; i<n; i++) a[i] = "1234";
    s = a.join("");
    d4 = new Date();

    a = d2.getTime() - d1.getTime();
    b = d4.getTime() - d3.getTime();
    c = ((b / a) * 100).toString();
    WScript.Echo([
        a,
        b,
        c.match(/.*\.[0-9]{2}/) + "%"
    ].join("\n"));

これはメモリの再確保が繰り返し行われる += ではその処理に
多くの時間が割かれてしまうということです。join() の方は
全体のサイズを算出してから一度だけメモリ確保の処理を
行うだけですので高速になります。また各要素のサイズは
文字列が BSTR ですから長さ情報は参照するだけで取得できます。
null コードが見つかるまでスキャンするといった処理は
介入してきません。
除算を避けるのはCPUが遅かった時代のCなんかでの常套手段
今はコンパイラが最適化してくれるから書かないけど・・

別に2のべき乗だけでなく
Math.floor(a/b) → a/b|0
とかもどう?
45IUnknown:02/04/12 00:52
>44
そういった話やアイデアは面白いですね。細かいところですが
ためになりますよ。


>11
「あっちでよろしくと言われた件について」
http://pc.2ch.net/test/read.cgi/win/1009175619/l50

煽りなら放置と思っていたのだけれど、他ならぬ 11さんのご指名があったので
11さんに対する回答の意味も含めて...

_stdcall や _cdecl は関数が呼び出されるときにパラメータがスタックに
どのような順序で渡されるか、関数が値を返すときにスタックは呼び出し側
、関数側のどちらがクリアするか、などを取り決めた呼び出し規則です。
ちなみに Win32 API 関数はすべて stdcall 呼び出しになっているため(つまり
エクスポートされている関数には _stdcall 識別子が使われている)、DynaCall
では "f=s" にしておかないと正しく呼び出すことが出来ません。stdcall は
パラメータの渡し順が右から左であること、スタックに積まれたパラメータは
呼び出された側がクリアすることになっています。_cdecl は C 言語の呼び出し
形式でありスタックの積み方は同様ですがパラメータは呼び出し元でクリアする
必要があります。
DynaCall は Win32 API 関数を呼び出すためのコンポーネントであるのに
何故 _cdecl までもが用意されているのでしょうかね。はっきりとした
ことはわかりませんが、例えば VB から利用できないように _stdcall 以外で
修飾された関数も呼べるようにしたというところでしょうか(Visual Basic で
Daclare ステートメントを使う場合、DLL の関数が stdcall 呼び出し規則に
従っていることを前提としているため)。

あと別件で DynaCall のソースを見ていて気付いたんですが、呼び出し形式の
デフォルトは _stdcall になっているようで、引数に "f=s" を指定しなくても
正しく関数を呼び出すことが出来ます。私自身 "f=s" を指定しなければならない
必然性を感じていなかったので、省略可能ってことで納得です。
レアなケースで _cdecl の関数も呼び出せるという程度に考えておけばよいでしょう。
46IUnknown:02/04/12 00:55
話は変わりますが DynaCall を使って文字列変数のポインタを取得する
関数を書いてみました。

  Set UserWrap = CreateObject("DynamicWrapper")

  str = ""
  ptr = VarPtr(str)
  WScript.Echo ptr

' 文字列型変数のポインタを取得する関数
  Function VarPtr(arg)
    UserWrap.Register "shlwapi.dll", "StrCatW", "i=wl", "f=s", "r=l"
    VarPtr = UserWrap.StrCatW(arg, 0)
  End Function

この関数は VB や VBA でモジュール関数として組み込まれている
VarPtr 関数と同じ機能を提供します。実際にこれらの環境で
両方の関数を実行すれば同一の値が返ってくることが確認できると
思います(その場合上記の関数の名前は変えておいてね)。第二引数は
null ポインタとして 0 を渡していますが、引数の型を w に変更
して "" (長さ0の文字列) などを渡しても構わないと思います。
私の場合は余計な文字列が生成されるのを避けただけです。
JScript の人は上記を参考に自分で作ってみてください。
今のところ試していませんが、構造体のメンバに文字列のポインタ
などを指定しなければならないようなときに使えるかなと
思っています。

Visual Basic での VarPtr 関数の確認
(1) オブジェクトブラウザで VBA ライブラリを選択する
(2) 非表示のメンバを表示させる
(3) 左ペインで _HiddenModule というモジュールを選択する
(4) 右側のペインに VarPtr が表示される
47IUnknown:02/04/12 01:18
構造体を扱うモジュールの開発状況です。

http://members.tripod.co.jp/IUnknown/WSH/DynaCall/

まあ、大したことは書いてませんが...。
48IUnknown:02/04/12 22:17
毎度毎度、長文で失礼します。情報程度と読み流しください。

昨日、紹介したポインタを取得する関数について色々調べていたところ
VBScript では不具合があることがわかりました。これはVBScript 言語
エンジンに依存してしまうため、おそらく回避は不可能と思われます。

まず結論から言いますと昨日紹介した関数は JScript で作成する必要が
あります。以下が JScript で書き直した関数です (StrCatW() はシェルの
環境に依存するので lstrcatW に変更しました)。

    function JS_VarPtr(arg) {
        UserWrap.Register("kernel32.dll", "lstrcatW", "i=ww", "r=l");
        return(UserWrap.lstrcatW(arg, ""));
    }

また昨日の VBScript による関数ですが DynaCall の仕様に従うならば

    Function VBS_VarPtr(arg)
        UserWrap.Register "shlwapi.dll", "StrCatW", "i=wl", "r=l"
        VBS_VarPtr = UserWrap.StrCatW(CStr(arg), 0)
    End Function

としなければならないところです。API 関数に渡す引数に文字列変数が
使われる場合(StrCatW() の第一引数)、CStr により文字列型の VARIANT
に変換しなければなりません。しかし CStr は変数 arg の型を直接変換
するのではなく新たに VARIANT を作成します。つまり上記のように書くと
StrCatW() に渡されるのは arg ではなく新たに生成された VARIANT に
なってしまい、取得されるポインタも arg のものではありません。
このような理由から昨日は CStr を付けなかったのですが、やはりこれが
動作に影響するようです。 DynaCall は文字列型の引数には VARIANT が
来ると期待していますが、そうではなくなるからです。つまり VBScript
では arg そのものを引数に渡すことができないようなのです。
(引数の型 's' や 'r' は内部で暗黙的な文字コードの変換が行われて
しまうため、同様の理由で不可)
49IUnknown:02/04/12 22:17
その点 JScript では正しく渡すことができます。以下は引数に文字列のポインタ
使って MessageBox() を呼び出すサンプルです。引数としてポインタを渡す場合は
DynaCall 側で 'l' を指定します ("i=hllu" の部分)。また文字列は Unicode
扱いなので MessageBoxA() ではなく MessageBoxW() を呼ぶことになります。
また文字列は NULL文字で終わる必要があります。


====================
varptr.wsf
====================

<job>
  <script language=JScript>
    function VarPtr(arg) {
        UserWrap.Register("kernel32.dll", "lstrcatW", "i=ww", "r=l");
        return(UserWrap.lstrcatW(arg, ""));
    }
  </script>
  <script language=VBScript>
    Set UserWrap = CreateObject("DynamicWrapper")
    UserWrap.Register "user32.dll", "MessageBoxW", "i=hllu", "r=l"

    s1 = "MessageBox (UNICODE)" & vbNullChar
    s2 = "From DynaWrap Object" & vbNullChar
    ret = UserWrap.MessageBoxW(Null, VarPtr(s1), VarPtr(s2), 3)
    WScript.Echo ret & "番のボタンが押されました。"
  </script>
</job>


もし VBScript で文字列変数そのものを正常に渡す方法を
知っている人がいましたら教えてください。
50IUnknown:02/04/13 12:20
クリップボードのテキストを取得するサンプルを書いてみた。
DynaCall がよくわからなくなってきた...。詳しくは以下のページで。

http://members.tripod.co.jp/IUnknown/WSH/DynaCall/helpme.htm

@OwnRisk ですが動作報告いただけると助かります。
PerlScriptってどうよ?

漏れはASP以外では使う意義を見出せないのだが......
5211:02/04/28 18:11
TLBINF32.DLL(ProgID=TLI.TLIApplication)を使って、COMのメンバの
helpstringを読み出すには、どうしたら良いのでしょうか?

MemberInfoクラスには、Property HelpString([LCID As Long]) As Stringという
プロパティがあるのですが、これを参照しても、長さ0の文字列が返って来るのみです。
引数に何か値を与えてやればいいのでしょうか?
それとも、まったく別のやり方で、helpstringを取得することが可能なのでしょうか?
5311:02/04/28 18:16
途中まで試しに書いてみたコードです。
http://pc.2ch.net/test/read.cgi/win/1009175619/819-820
54デフォルトの名無しさん:02/04/28 18:27
おーずっとsage進行だったのか、全然気づかなかった。
単にhelpstringが設定されてないだけとちがうん?
5611:02/04/28 18:51
>>55
げっ、本当だ。
例として取り上げた、wshom.ocxには、もともとhelpstringが
設定されていないのですね。
他のタイプライブラリでは、問題なく動作することを確認しました。

激しく鬱だ。お騒がせして申し訳ありませんでした。
javascriptってどんなウィジェットが使えるんですか?
VBScriptってFormat関数ないのな・・・
桁揃えるだけなのに、いちいちスペース挿入するの作らにゃならんとわ・・・

Cでやればよかったよ・・・(;;)
>>58
そんなに面倒か ? 桁あふれ考えなくていいなら、
Right(Space(n) & x, n) で良いと思うが。
VSA による JScript .NET は実行開始までに時間が掛かりすぎるなあ。
お手軽スクリプトの実行にはまだ WSH による JScript が当分主流でしょう。
機能的には雲泥の差がありますけれども。VB .NET と VBScript の関係も
同様でござる。
>>60
同意。ある意味では完全に別物。
用途によるが、WSHの代わりにはなりえない。<JScript.NET
62IUnknown:02/05/13 21:54
久し振りの書き込みです。
60さん、61さん、代わりにならないなら使いこなしてやりましょう!!

巷では .NET Framework SDK (日本語版) の無償提供開始により
.NET プログラミングが本格的に浸透し始めてきたように思います。
COM は消え行く運命であることに間違いはないのですがその技術は
.NET に受け継がれていくのでその知識が無駄になることはないでしょうね。
また消え行くにせよ、これまでの資産をいきなり手放すことなど出来るわけも無く
.NET では COM との相互運用が十分考慮されているようです。

例えば .NET クライアントから COM コンポーネントを利用したり、
COM クライアントから .NET コンポーネントの利用したりすることが可能です。
後者は WSH ユーザにも有益な機能であると思っています。ということで
スクリプトプログラマ向けのちょっとした .NET お遊びをしてみます。

以下は VB .NET で .NET コンポーネントを作成し
それをスクリプトから呼び出してみるサンプルです。
あらかじめ .NET Framework SDK をインストールしておいてください。

http://www.microsoft.com/japan/msdn/netframework/downloads/sdk.asp


' sample.vb

Namespace Clannad
  Public Class Serius
    Public Function Add (ByVal x As Integer, _
        ByVal y As Integer) As Integer
      Return x + y
    End Function
  End Class
End Namespace
63IUnknown:02/05/13 21:55
まず上記ソースファイルをコンパイルします。

vbc /t:library sample.vb

すると sample.dll が作成されます。次に COM コンポーネントとして
利用できるようにレジストリに登録します。

regasm sample.dll

sample.dll は wscript.exe あるいは cscript.exe と同じフォルダに
置いておく必要があります。
では VBScript からこのコンポーネントを呼び出してみます。


' test.vbs

Set obj = CreateObject("Clannad.Serius")
WScript.Echo obj.Add(12, 24)


VS .NET に手が出ない方も無償提供される SDK をインストールすれば
.NET コンポーネントを作成することが出来ます。.NET がもう少し普及するまで
また JScript .NET、VB .NET のスクリプトホストの実行速度が改善されるまで
COM コンポーネントにラップした .NET コンポーネントを VBScript、JScript で
楽しんで見るのもいいかと思います。VBScript や JScript では手にすることが
出来なかった様々な機能を利用することが出来るんですからね。

上記のサンプルは VB .NET ですが JS .NET でも同様のことが出来ますので
JScript ユーザの方も挑戦してみてはいかがですかね?

ちょっとしたお遊びでした。
>>62-63
サンプル試してみました。
この方法なら、実行速度は気になりませんね。
しかし、わざわざレジストリに登録するのに、なぜDLLをexeと
同じディレクトリに置く必要があるんでしょう?

私はWin98SEで、SDKがインストールできないので、Webでの情報が
もっと充実するまでは.NETを利用するのは苦しい・・・。
65IUnknown:02/05/14 01:20
ProgID Clannad.Serius
CLSID {9E8FF145-2B8C-3416-AD3D-1BBBCFD540C5}

レジストリ情報を眺めるとわかりますが、実際にコンポーネントとして登録されるのは
mscoree.dll であり、このライブラリが .NET コンポーネントを COM コンポーネントのように
利用するためのラップ処理を行います。つまり sample.dll のパス情報がレジストリに
登録されているわけではありません。以下は SDK ドキュメントからの引用。

//////////////////////////////////////////////////////////////////

.NET クラスを COM に登録または登録解除するには、コマンド ライン ツールの
アセンブリ登録ツール (Regasm.exe) を実行する必要があります。Regasm.exe は、
COM クライアントが特別な処理を行わなくても .NET クラスを使用できるように、
クラスに関する情報をシステム レジストリに追加します。RegistrationServices クラスは、
これと同等の API 機能を提供します。

Regasm.exe は、HKCR/CLSID レジストリ キーの下に、.NET クラスの CLSID の
新しいエントリを作成します。1 つのクラスに Regasm.exe を何回使用しても、そのクラスの
COM での CLSID は変更されません。

HKCR\CLSID\{0000...0000} キーの下には、既定値としてそのクラスの ProgID が設定され、
Class と Assembly という 2 つの名前付きの値が新しく追加されます。ランタイムは、
レジストリから Assembly の値を読み取り、その値をランタイムのアセンブリ リゾルバに渡します。
アセンブリ リゾルバは、名前やバージョン番号などのアセンブリ情報に基づいて、そのアセンブリを
検索します。ただし、アセンブリ リゾルバがアセンブリを検出する前に、そのアセンブリが署名されて
グローバル アセンブリ キャッシュにインストールされているか、またはアプリケーション パス上に
配置されている必要があります。アプリケーション パスから読み込まれたアセンブリは、
そのアプリケーションからしかアクセスできません。共有アセンブリは、署名付きでグローバル アセンブリ キャッシュに
インストールする必要があります。

Regasm.exe は HKCR\CLSID\{0000...0000} キーの下に、InProcServer32 キーも作成します。
このキーの既定値は、共通言語ランタイム (Mscoree.dll) を格納している DLL の名前に設定されます。

////////////////////////////////////////////////////////////////////////

vbc.exe, regasm.exe とも /? オプションでヘルプが表示されます。
先程書き忘れましたがレジストリ情報の削除は

regasm /u sample.dll

です。
66デフォルトの名無しさん:02/05/14 01:39
私もやってみました。regsvr32とちがって、\winntとか\winnt\system32とかに
入れなきゃいかんのですよね。ちょっと残念。使用元がvb exeとかならそれと同じ
ディレクトリに置けば動くんですが。

最初jscriptから使おうとして、*.jsファイルと同じとこに置いても
動かない。web探して「厳密名つけてgacに入れるヨロシ」という記述を
見たので挑戦……半日かかりましたよ。厳密名つけるの面倒です。
6764:02/05/14 01:42
>>65
なるほど。詳細なレス感謝です。

登録情報の削除は/uでいけるんですね。
ヘルプでは/unregisterとしか出ないんで・・・。

う〜ん、コンパイラはインストールできるのにドキュメントは
インストールできんとは・・・。なんていけずなんだ、M$。
scriptって手書きって意味でしょ。
69IUnknown:02/05/14 08:51
参考までに JScript .NET で作成するサンプルです。

// sample2.js

package Clannad
{
  public class Bamba
  {
    public function Add (x : int, y : int) : int
    {
      return x + y;
    }
  }
}


コンパイルは

jsc /t:library sample2.js
IUNKNOWNさんって、M$の社員かしら??
なんか、そんな気がした。(それが良い悪いということを言いたいわけじゃない)
71デフォルトの名無しさん:02/05/26 09:09
HTML内で使って戻り値を得るにはどうすれば・・・
72IUnknown:02/06/01 01:02
書くのも久し振りなら読むのも久し振りだったりして。といっても
やっぱりレスは少ないですね(当たり前か)。

ところで皆さん MSDN マガジンは読みましたか?WSH に関する
かなり興味深い記事に結構なページが割かれてますよ。私の所感では
MS は WSH と COM の手を切る可能性はあっても WSH の存在自体は
否定していないような気がします。過去の遺産となる COM に関しても
.NET がラップしていくことになるでしょうね。WSH は .NET と
手を組んでまだまだ進化していくのではないでしょうか?
.NET の時代、WSH = COM という図式はもう古いのかも知れません。
(記事の内容からは少々逸脱したお話になってしまった)

>IUNKNOWNさんって、M$の社員かしら??
うーん、私は M$ の社員ではないです。一体何者なんでしょうかねえ。
自分でも時々わからなくなります。


>wsc化して、汎用コードにできませんかねえ?
>そうすれば、多少は実用性も出てくるんじゃないかと。

2ヶ月近く前の話題になりますが、近々公開出来そうかなと...。
週末に少しずつ書いていたのですが、ある程度形になってきました。
これからヘルプに取り掛かろうと思っていますが、近々と言いながら
マイペースでのんびり屋の私にとってはヘルプの作成に数週間ぐらい
かかったりするかも知れません。

構造体の定義/呼び出しなどに関しては、以前公開した
JScript 版よりすっきりとした構文で書けるようにしてあります。
また構造体以外にも DynaCallを便利に利用する幾つかの機能を
盛り込んでみました。

7311:02/06/01 01:07
>>72
へー、WSHに未来があったとは知らなかった (w

MSDNマガジンって、普通に本屋さんで買えるんですか?
(なんも知らなくて、すんません…)

wsc、楽しみにしてます。


ところで、Windows板の方のWSHスレですが、part 2が立ったみたいなので、
一応ご報告しときます。

お前ら、wsh使ってますか? Part2
http://pc.2ch.net/test/read.cgi/win/1022248379/
>>72
特集2のところでしょうか?Webで読めないようで残念です。<MSDN Magazine
75IUnknöwn:02/06/04 12:48
ヘルプ作成ing の IUnknöwn です。

>11さん
新スレの情報感謝です。いつもお世話になります。
もう解決したかもしれないですが MSDN マガジンはちょっと大き目の
書店であれば置いていると思います。また本家のサイトでは Web上で
公開される特集記事も少なくありません。お金は無いけど英語なら
大丈夫という方は是非本家に立ち寄ってみてください (スクリプトは
オンにしておくほうが吉)。
http://msdn.microsoft.com/msdnmag/default.asp?ID=0

>74さん
WSH に関する MSDN マガジンの特集記事はこちらで全文読むことができます。(英語)
http://msdn.microsoft.com/msdnmag/issues/02/05/wsh/print.asp
7674:02/06/05 00:23
>>75
ありがとうございます。見てみます。

#ハンドル変えたんですか?
77IUnknown:02/06/06 00:09
>74さん
え〜と、ウムラウトが使えるかなと思って試しただけです。
あんまり意味はないです...。紛らわしいことしてスンマセン。

質問。WSFからWSFは呼べませんか?
■caller.wsf
<?xml version="1.0" encoding="Shift_JIS"?>
<package>
<?component error="true" debug="true"?>
<job id="nongeneral">
<?job debug="true"?>
<script language="VBScript">
<![CDATA[
MsgBox "ここに汎用性のないコードを記述します。"
]]>
</script>
<script src="callmodule.wsf">
</script>
</job>
</package>

■callmodule.wsf
<?xml version="1.0" encoding="Shift_JIS"?>
<package>
<?component error="true" debug="true"?>
<job id="general">
<?job debug="true"?>
<script language="VBScript">
<![CDATA[
MsgBox "ここに汎用性のあるコードを記述します。"
]]>
</script>
</job>
</package>

こんな感じで出来たら、VBS Unitの作成の手前、都合いいです。
現状はエラーメッセージが「ステートメントがありません」です。
79蛍光パン:02/06/16 23:54
>78
VBSでインポートしちゃだめって理由はあるの?

■callmodule.vbs
MsgBox "ここに汎用性のあるコードを記述します。"

で十分かと
>79
レスありがとうございます。
元形(callmodule)のテストを行うのが目的なので、
1.テスト対象がWSFでもテストできるのか大枠をつかみたい
2.元がWSFなら簡単にスクリプトをWSC化できるかなって思いまして。

これが出来なければ、それなりに考え直すって段階です。
81IUnknown:02/06/24 21:56
非常に遅れましたがスクリプトコンポーネントを公開しました。

サイトはまだ完成していません。ヘルプの作成がなかなか進まないので
サンプルコードを多めに作っておきました。大体の感じを掴めていただけたらと思います。
またサイトに掲載しているサンプルを簡単に実行できる
ユーティリティ(IEコンテキストメニュー用スクリプト)も作ったので
よろしければお試しください。

http://members.tripod.co.jp/IUnknown/WSH/dwhelper/

現在はヘルプの作成の他、dynwrap.cpp を少々いじったりしています。
VBScript でも JScript と同様に文字列型変数を直接渡せるようにしたりとか...。
後は 9x系の環境で上手く動作しない原因も調べてみるつもりです。

※ 以前サイトに掲載していたメールアドレスが間違っていました。
× [email protected]
[email protected]
8211:02/06/27 02:47
>81
なんか表示されません…。

Win2000sp2+IE6。スクリプトなどは実行許可にしてあります。
83IUnknown:02/06/27 20:57
>11氏
お久し振りです。

えーと、UTF-8 で見てください。
スクリプト等は使用していません。

以上よろしくです。
84デフォルトの名無しさん:02/06/29 01:11
Win2KでVBS書いてるのですが、InputBoxで
キャンセルボタンが押されたか、
空白状態でOKボタンが押されたかを見分ける方法って、
どんな感じになるのでしょうか?
以下のように書いてとりあえずやりたいことは出来ましたが、
いまいちきれいじゃ無いような気がするんです。

retCode = InputBox("値をいれてください")

If retCode = "" Then
  If retCode = False Then
    MsgBox("キャンセルボタン")
  Else
    MsgBox("空白状態でOKボタン")'
  End If
End If
str=InputBox("値をいれてください")
if IsEmpty(str) then msgbox("キャンセルボタン") else msgbox(str)
8684:02/06/30 04:12
>>85
Thanks!!!

というか、IsEmptyでなくても、str = Falseならば、
キャンセルボタンだと言うことがわかりました。
ちょっと発想を変えればよかったのね>漏れ
すみません、質問です。
実行中のスクリプトが、自分自身のプロセスIDを得るにはどうすればよろしいでしょうか。
現在は、WMIからExecQueryで SELECT * from win32_process where Name = "wscript.exe" を
投げていますが、これでは複数のwscriptが動いている場合、どれが自分なのかが判断できず
にいます。
当方の環境はWin2000Serverでして、個人所有にかかるマシンではないため、COMを追加
しようにもできずに困っています。

88デフォルトの名無しさん:02/07/24 09:15
ageage
hage
失敗禿