いりや さん 2004年 07月 03日 15時 16分 32秒

ばんのしゃーによかばんたさん、

| >いりや さん 2004年 07月 02日 13時 52分 51秒
| >うーん、this 擬似変数に何かがバインドされているのは typeof() で分かっ
| >たのですが、IWebBrowser2 (InternetExplorer.Application) オブジェクト
| >のプロパティーを表示させようとすると空になっているようです。ちょっと
| >これはもう少し要調査ですね。
|
| 変ですね。
[snip]
| で、IEのXボタンを押すとPopupでIEの名前が表示されましたよ。

こちらもうまくいくことが確認できました!

うまくいかなかった原因がわかりました。

最初は、イベントハンドラ Dialog1_OnQuit ではなくてそこで呼んでいる
setOnQuitFlag の中で this を参照していました。これは誤り、Dialog1_OnQuit
の中で this を参照して IWebBrowser2 (InternetExplorer.Application) オブ
ジェクトを取得できました。

それに伴い、this を dialogArray から対象ウインドウを検索するキーにするよ
う、setOnQuitFlag に渡してやるよう変更してやり、イベントハンドラを三つか
ら一つにまとめることもできました。setOnQuitFlag() はこんな感じにになりま
した。setOnQuitFlag(this, -2) のように呼びます。(インターフェイス変更に
伴う修正箇所は省略)

function setOnQuitFlag(from, tristateValue) {
    var dialog = dialogArray.detect_(function (each) { return each.window == from });
    dialog.onQuit = tristateValue;
}

function Array.prototype.detect_(discriminator) {
    return this.detect_ifNone_(discriminator, function () { throw Error('Not found: ' + discriminator) });
}

function Array.prototype.detect_ifNone_(discriminator, exceptionHandler) {
    for (var i = 0; i < this.length; i++)
        if (discriminator(this[i]))
            return this[i];
    return exceptionHandler();
}

一応ここまで修正してあるウインドウ操作のシナリオではうまくいくことが確認
できましたがいくつかのシナリオではウインドウが閉じないなどの不具合も見つ
かりました。

このあたりは、スクリプトホスト (wscript.exe) 、イベントハンドラ、HTML 側
の SCRIPT 要素それぞれの実行モデルをもう少し整理したうえであらためてどこ
に何を配置すればユーザーインターフェイスがぎこちなく動くかを考えた上でま
た書き直そうとおもいます。

ではでは。

いりや

【おじさま】 さん 2004年 07月 03日 12時 24分 46秒

・・・(^^;)

ばんのしゃーによかばんた さん 2004年 07月 03日 02時 16分 32秒

>【おじさま】 さん 2004年 07月 02日 18時 51分 11秒
>本業が多忙で生活に追われ(^^;)年齢的にプログラミングも忘れつつあり

何を仰る。プログラミングは年齢に関係ないでしょうに。
大昔、プログラマ30歳?定年説?とか、聞いたことがありますが、最近は聞かないですね。
それに、おじさま、さんは、たしか、私よりお若いはず。
私なんぞは四十肩か五十肩かは両肩済み。
遠視、突発性難聴後の耳鳴り、飛蚊症、硝子体剥離などは年齢に関係しますが、
プログラミングは現役引退後の趣味にちょうどよいですよ。

ばんのしゃーによかばんた さん 2004年 07月 03日 02時 14分 03秒

>いりや さん 2004年 07月 02日 13時 52分 51秒
>うーん、this 擬似変数に何かがバインドされているのは typeof() で分かっ
>たのですが、IWebBrowser2 (InternetExplorer.Application) オブジェクト
>のプロパティーを表示させようとすると空になっているようです。ちょっと
>これはもう少し要調査ですね。

変ですね。
――――――――――――――――――――――――――――――――――――――
var wShell=new ActiveXObject("WScript.Shell");
var ie=WScript.CreateObject("InternetExplorer.Application","IE_");
ie.Visible=true;
WScript.Sleep(100000);
WScript.Quit;

function IE_OnQuit(){
wShell.PopUp("OnQuit" + this.Name);
}
――――――――――――――――――――――――――――――――――――――
で、IEのXボタンを押すとPopupでIEの名前が表示されましたよ。

ばんのしゃーによかばんた さん 2004年 07月 03日 02時 12分 40秒

>管理人むたぐち さん 2004年 07月 02日 08時 56分 15秒

MVP、おめでとうございます。益々のご活躍を。

>改良版最新verを実行してみたんですが、Favoritesは問題なかったものの、

どうなんでしょう。折角なんですが、
UIHelper.ImportExportFavoritesがあるのに、誰か使うでしょうか。

>> url2htm
>Historyは55行目の
>: : : : ts.WriteLine "<a href=""" & arr(1) & """>" & arr(0) & "</a><br>"
>でエラーになったので、そこだけOn Error Resume Nextすると
>GetDetailsOfで、検索エンジン等のURLはエンコードされた
>状態で値を返してくるのが問題なんだと思います。
>あと、>と<を&をsanitizeしないと結果をブラウザで表示すると
>崩れることがありますね。
>要修正です…ってこれ元々私のスクリプトでしたっけ。

そもそも、GetDetail(,-1)を使うのがよくないのではないでしょうか。
GetDetail(,0) - インターネット アドレス --- こっちはURLEncodeされている。
GetDetail(,1) - タイトル =FolderItem.Name
を使えば問題ないように思います。

修正版です。※今度こそ収束して頂戴。
――――――――――――――――――――――――――――――――――――――
'IEのお気に入りをHTMLファイルにするスクリプト

'IEのお気に入りを一つのHTMLファイルにまとめます。
'そこそこ時間がかかるので、注意。
'このままでは出力されるHTMLは非常に簡素なので、各自味付けしてください(^^;

Set fso = WScript.CreateObject("Scripting.FileSystemObject")
set wShell = WScript.CreateObject("WScript.Shell")
Set Shell = WScript.CreateObject("Shell.Application")

'Set Folder=Shell.NameSpace("C:\Windows\history")
'↑の場合、「履歴」をHTML化します。
'ただし、履歴をため込んでいる場合(999日など)は、死ぬほど時間がかかります。
'10000件のURLだと1時間くらいかかる…かも。
Const ssfHISTORY = 34
Const ssfFAVORITES = 6
Set Folder=Shell.NameSpace(ssfFAVORITES)

For Each arg In WScript.Arguments
If IsNumeric(arg) Then
Set Folder=Shell.NameSpace(CLng(arg))
Else
Set Folder=Shell.NameSpace(arg)
End If
Exit For
Next

strPath=Folder.Title & ".htm"
'出力するHTMLファイルのパス。既存ファイルは上書きされます。

WScript.Echo "ただいまから、" & Folder.Title & "をHTML化します。",strPath

Set ts=fso.CreateTextFile(strPath,True)

ts.WriteLine "<html><head><title>" & Folder.Title & "</title></head><body>"

Call RecSrch(Folder)

ts.WriteLine "</body></html>"
ts.Close
WScript.Echo "終了。"

Sub RecSrch(Folder)
: ts.WriteLine "<blockquote>"
: For Each FolderItem In Folder.Items
: : If FolderItem.IsFolder Then
: : : Set SubFolder=FolderItem.GetFolder
: : : ts.WriteLine "<p>" & SubFolder.Title & "<br>"
: : : Call RecSrch(SubFolder)
: : : ts.WriteLine "</p>"
: : ElseIf FolderItem.IsLink Then
: : : Set Link = wShell.CreateShortcut(FolderItem.Path)
: : : ts.WriteLine "<a href=""" & Link.TargetPath & """>" & FolderItem.name & "</a><br>"
: : ElseIf FolderItem.IsFileSystem Then
: : : : ts.WriteLine "<a href=""" & FolderItem.path & """>" & FolderItem.name & "</a><br>"
: : Else
: : : str=Folder.GetDetailsOf(FolderItem,0)
: : : If str<>"" Then
: : : : ts.WriteLine "<a href=""" & str & """>" & FolderItem.name & "</a><br>"
: : : Else
: : : : ts.WriteLine "<a href=""" & FolderItem.path & """>" & FolderItem.name & "</a><br>"
: : : End If
: : End If
: Next
: ts.WriteLine "</blockquote>"
End Sub

【おじさま】 さん 2004年 07月 02日 18時 51分 11秒

>Microsoft MVP for Visual Developer - Scripting

今回は本当におめでとうございます。

本業が多忙で生活に追われ(^^;)年齢的にプログラミングも忘れつつあり
すっかりご無沙汰していますが目だけは通しています。

むたぐちさんもお身体に気を付けて益々ご活躍下さい。

shobohn さん 2004年 07月 02日 18時 47分 41秒

To: むたぐち さん

MVPすごいですね。おめでとうございます。
これからもマイペースでがんばってください。

いりや さん 2004年 07月 02日 16時 15分 07秒

つれづれなるままに・・・。

・むたぐちさん

MVP おめでとうございます!

今後ともスクリプティングの楽しい世界をコミュニティーの皆さん
で共有できるといいですね。わたしも及ばずながらお手伝いをさせ
ていただけたらとおもいます。時代はもう Lightweight Language
でインタラクティブ・プログラミングでしょ。

    http://ll.jus.or.jp/llw2004/


・Smalltalk-style Programming Libraray (StPL)

じゅん for Smalltalk とよばれる 3 次元グラフィックマルチメディ
アライブラリがあるのですが、これを SRA のスタッフの方が Java
に移植する際に、足場として StPL と呼ばれる Smalltalk 特有の
機能をサポートするライブラリを一緒につくられています。

    http://www.sra.co.jp/people/nisinaka/Jun4Java/index_ja.html
    http://www.sra.co.jp/people/aoki/Jun/Main.htm

それで、最近 JScript でプログラミングをしていて Smalltalk で
よく使っているオブジェクトが欲しくなり、StPL の一部を
ECMAScript (or JScript) に移植しています。

きちんと移植している訳ではなく、メモリにそのオブジェクトを出
現させるのを第一優先にしています。そのため Smalltalk の仕様
にあるすべてのプロトコルをサポートをしているわけではありませ
ん。

でも、ブロッククロージャ (関数オブジェクト) と遅延評価をつかっ
たプログラミングのしやすさが格段にあがります。これだけでも十
分ありがたい。

    例:
    http://iriyak.adam.ne.jp/wiliki/uwsc.cgi?iriyak%3aJScript&l=jp
    の
    ・サクラエディタのキーワードヘルプの生成器 (ジェネレータ)
    ・複数の InternetExplorer.Application オブジェクトを区別するてがかり (print-prop.js)
    ・Array オブジェクトの拡張 (Collection クラスのポーティングへの道)


StPL の移植については、WiLiKi をソースコードのリポジトリ・サー
バに見立てて使っていますのでよかったらご覧ください。編集履歴
で差分をトレースできます。

    http://iriyak.adam.ne.jp/wiliki/uwsc.cgi?iriyak%3aJScript%3aLibrary&l=jp


・Dynamic HTML Object Model

さきの記事でもふれましたが、これまで InternertExplorer.Application
の document プロパティーなどを通じて Dynamic HTML Object
Model を参照することはよくしていましたが、作ることに転じてみ
ようと msdn やインターネット上のリソースを読み進んでいます。

リンクでご紹介した枠組みは、いずれも document オブジェクトを
つくるのに利用できるものです。大掛かりなものは Microsoft も
Component Object Model で提供しているようですが、自分でスモー
ルセットをこさえてみるのも悪くない。そう思って StPL の集まり
(Collection) クラスと連携させながらそうした枠組みを考えてみ
ています。


・Microsoft が提供する Component Object Model

JScript では ActiveXObject コンストラクタを使って COM オブジェ
クトにアクセスできますが、素でそのまま使っていると他の組込み
オブジェクトとの親和性がよくなかったりして具合が悪い。

例えば toString() に応えてくれないとか
InternetExplorer.Application>>navigate() が非同期メソッドな
ので待つメソッドを追加したいがプロトタイプに追加するアプロー
チはとれないとかそういった話です。

このあたりの親和性を高める策は何かないものか模索しています。

簡単に思いつくのは、それを包むオブジェクトを用意するというも
のです。プロパティーへの直のアクセスを禁止してアクセッサ (セッ
タ、ゲッタ) メソッドを用意します。メソッドはそのままオリジナ
ルのメソッドを起動するようにします。

ただ、アクセッサメソッドを一セット用意することになるのでちょっ
と面倒かもしれないなと感じています。

ここのところを、何かブスッと差し込めば一部のメソッドだけを追
加できるようなオブジェクトに仕立て上げる、そんな夢のようなア
ダプタがあればいいなあと、アダプタと名の付いた枠組みを色々と
眺めてはいますがまで模索中です。


・ITextStream インターフェイス

WScript.{stdin,stdout} や File>>openAsTextStream() メソッド
の返すオブジェクトは ITextStream インターフェイスをサポート
するのですが、Smalltalk の Stream クラスのようにもっと流れ
(Stream) を積極的に使いたい。

    青木さん, Smalltalk Textbook 21: Stream
    http://www.sra.co.jp/people/aoki/SmalltalkTextbookJ/textbook21.html

以前に、クリップボードを ITextStream インターフェイスでアク
セスできるように File>>openAsTextStream() の返したオブジェク
トを包む JScript オブジェクトを試作してみたけれど、いまいち
な感じがしました。

    いりや さん 2003年 10月 30日 02時 34分 24秒
    http://www.roy.hi-ho.ne.jp/mutaguchi/bbs/list93.shtml

this.refresh() メソッドを使ってプロパティーの同期を取ってい
るのですがあまり美しく感じないし、読み込み専用のプロパティー
だけを扱うのならばいいのですが、プロパティーへの書き込みを許
す場合は使えないからです。(Windows Script Component は書き込
み時にもフックを仕掛けられるんですけどねぇ。)

なので、一度 ITextStream インターフェイスを忘れて Smalltalk
の Stream を普通に JScript の世界に持ってこようかと考えてい
ます。

以上、とりとめもない話でした。

いりや

いりや さん 2004年 07月 02日 13時 52分 51秒

ばんのしゃーによかばんたさん、

| 同じ名前のイベントハンドラにして、ハンドラ内で発火元オブジェクトを識別出来るようです。

うーん、this 擬似変数に何かがバインドされているのは typeof() で分かっ
たのですが、IWebBrowser2 (InternetExplorer.Application) オブジェクト
のプロパティーを表示させようとすると空になっているようです。ちょっと
これはもう少し要調査ですね。


| 現在、IEのイベントをWScript側と接続するのではなく、
| IE側に動的にスクリプトを組み込むことを模索してます。
| これなら、イベントオブジェクトが利用できますし、
| また、WScript側が終了した後も、IEだけで処理が続行できます。
| なんか、応用が効きそうです。:-)

はい。イベントハンドラを WSH の世界で実行するようなモデルでは、どうし
てもイベントハンドラの並行処理が期待されるケースで WSH に引きずられて
しまうことが避けられないのでそこは WSH から切り離しておくのがよさそう
です。

ただ、もう、ベタに HTML の文字列表現を書いて、write() メソッドに与え
るのはやめて、そふぃあさんの HTMLBuilder と js-html のような枠組みや
Sjoerd Visscher さんの高階関数をつかった HTML の生成手続きや、

JavaScript Object Notation (JSMON) を利用して、HTML の文字列表現から
は開放されたいと感じています。

そふぃあさん, HTMLBuilder, js-html
http://members.jcom.home.ne.jp/jintrick/Personal/HTMLBuilder.html
http://members.jcom.home.ne.jp/jintrick/Personal/js-html.html

Sjoerd Visscher さん, Higher Order Programming in Javascript
http://w3future.com/html/stories/hop.xml

Douglas Crockford さん, JavaScript Object Notation (JSMON)
http://www.crockford.com/JSON/index.html
http://www.crockford.com/JSON/js.html


| あれ、やっぱり。もしかして、読んでないのかなぁ、と思ってたら、
|
| >ばんのしゃーによかばんた さん 2004年 05月 30日 15時 59分 28秒
| >Class_Terminate二題
| >こんな使い方が出来ます。

失礼、落としていました。こちらは読んでおきますね。

いりや

管理人むたぐち さん 2004年 07月 02日 09時 01分 08秒

To: よしお さん

どうもありがとうございます。

変な投稿はどうせ自動投稿のspamでしょうし、とりあえず放置してます。
2chなどでは良く見かけたんですけど、最近は2chもこの手の
spam対策を色々と行っていて、業者が書き込めなくなった分の
とばっちりが、うちとかに来てるのかもしれませんね。

管理人むたぐち さん 2004年 07月 02日 08時 56分 15秒

To: kkkkk さん

> スクリプトファイルについて聞きたいのですが、あるゲームを起動しようとすると「システムファイルをアップデートします。」とでで、OKしかなくて、OKをクリックすると「スクリプトファイルを開けません。」とでます。

これだけの情報ではこちらとしても何とも意見しかねます。
そのゲームのオフィシャルサイトなどを参照して、
同様の質問がないか検索する、もしくはサポートに問い合わせるなどで
対処してください。


To: ばんのしゃーによかばんた さん

> SelectionChangedが接続できました。

> ie.document.script.document.body.all.filelist.objectを接続するなんて、

> ie.document.script.filelist.object
> でもよいようです。

おおっ、これでShellFolderViewオブジェクトに外部から
Connectできるわけですか。
しかし、残念ながらWinXPでは、Scriptプロパティを参照するとエラーに
なってしまうので使えないんです、これが。
そもそもWinXPには「Web表示」が無いんですね。
したがって、このテクニックはWin2000/ME(/98も?)限定になると思います。

それと、"filelist"は、あくまでデフォルトのhttファイルでは
ShellFolderViewオブジェクトがfilelistという変数に格納されているという
だけであって、確定しているものではないことに注意が必要かもしれません。
(厳密にやるならTypeNameで調べるとか?)

まあ、httファイルをカスタマイズしてるような人は、
世界で500人くらいしかいないと思いますが。

> url2htm

さすがに大昔に書いたスクリプトだけあって、自分で見てもかなりダメですね。
多分、まだ再帰処理が良く分かってなかったんでしょうw

改良版最新verを実行してみたんですが、Favoritesは問題なかったものの、
Historyは55行目の
: : : : ts.WriteLine "<a href=""" & arr(1) & """>" & arr(0) & "</a><br>"
でエラーになったので、そこだけOn Error Resume Nextすると
一応最後まで実行されました。
というか、そもそもこのElse部分が実行される時点でヘンテコなことが
起こってると考えるべきでしょうね。

結局、
http://www.roy.hi-ho.ne.jp/mutaguchi/bbs/list104.shtml
http://www.roy.hi-ho.ne.jp/mutaguchi/bbs/list105.shtml
の、ふみふみさんの記事などを見てもらえればわかりますが、
GetDetailsOfで、検索エンジン等のURLはエンコードされた
状態で値を返してくるのが問題なんだと思います。

それどころか、FolderItem.Pathがそもそもまともな値を返さないこともあるみたいです。
それが、Else部分が実行されてしまう原因かもしれません。
これはもう、履歴が破損しているのに等しいので、ここまで対処することも
ないかもしれませんが。…ていうか私の履歴が破損してるだけかも。

あと、>と<を&をsanitizeしないと結果をブラウザで表示すると
崩れることがありますね。
要修正です…ってこれ元々私のスクリプトでしたっけ。

よしお さん 2004年 07月 02日 08時 52分 21秒

むたぐちさん、おめでとうございます。今後も宜しくご指導お願い
致します。けど、なんだか最近変な書き込み増えてる見たいですね。
誰か呼び水でもしてるのかな?

管理人むたぐち さん 2004年 07月 02日 07時 44分 00秒

トップページにも書きましたが、このたび、昨年1年間のこの掲示板での
活動が認められ、この私がMicrosoft MVP for Visual Developer - Scriptingに
認定されました。文字通り身に余る光栄です。
ご推薦をいただいた魔界の仮面弁士さん、日本MVP事務局のみなさん、
MVPプログラムアワードチームのみなさん、ほか、関係されたMicrosoft社のスタッフのみなさん、
本当にありがとうございました。この場を借りて御礼申し上げます。

正直、私なんかがMVPとかで良いのか?とも思いますが、今後もできる限りの
ことはやりますので(と言っても、今までどおりこの掲示板で
質問に回答とかするわけですが)、これからもよろしくお願いします>ALL

由真 さん (diss@jpcom.jp) 2004年 07月 01日 15時 30分 02秒

26歳の主婦ですが今流行のハプニングバーに
とても興味があり思い切って投稿して見ました。
どなたかご一緒して頂けませんか?
月か土曜日の夜と秘密厳守が条件です。
わがままな投稿ですいません
m(_ _)m

ばんのしゃーによかばんた さん 2004年 07月 01日 14時 48分 05秒

url2htmを更に修正。なかなか障害が収束しません。結構複雑で面倒臭いです。
検索のURLなどはGetDetail(,-1)では省略されてフルに取れないみたいなので、
ショートカットオブジェクトから取るように変更しました。
.urlと.lnkはIsLinkになるようですが、.urlはGetLinkできないみたいです。
なので、wShell.CreateShortCutを使います。
また、IsFileSystemを判定しないと、GetDetail(,-1)でファイルタイプとサイズを掴まされました。
これで、収束してくれればよいのですが。
――――――――――――――――――――――――――――――――――――――
'IEのお気に入りをHTMLファイルにするスクリプト

'IEのお気に入りを一つのHTMLファイルにまとめます。
'そこそこ時間がかかるので、注意。
'このままでは出力されるHTMLは非常に簡素なので、各自味付けしてください(^^;

Set fso = WScript.CreateObject("Scripting.FileSystemObject")
set wShell = WScript.CreateObject("WScript.Shell")
Set Shell = WScript.CreateObject("Shell.Application")

'Set Folder=Shell.NameSpace("C:\Windows\history")
'↑の場合、「履歴」をHTML化します。
'ただし、履歴をため込んでいる場合(999日など)は、死ぬほど時間がかかります。
'10000件のURLだと1時間くらいかかる…かも。
Const ssfHISTORY = 34
Const ssfFAVORITES = 6
Set Folder=Shell.NameSpace(ssfFAVORITES)

For Each arg In WScript.Arguments
If IsNumeric(arg) Then
Set Folder=Shell.NameSpace(CLng(arg))
Else
Set Folder=Shell.NameSpace(arg)
End If
Exit For
Next

strPath=Folder.Title & ".htm"
'出力するHTMLファイルのパス。既存ファイルは上書きされます。

WScript.Echo "ただいまから、" & Folder.Title & "をHTML化します。",strPath

Set ts=fso.CreateTextFile(strPath,True)

ts.WriteLine "<html><head><title>" & Folder.Title & "</title></head><body>"

Call RecSrch(Folder)

ts.WriteLine "</body></html>"
ts.Close
WScript.Echo "終了。"

Sub RecSrch(Folder)
: ts.WriteLine "<blockquote>"
: For Each FolderItem In Folder.Items
: : If FolderItem.IsFolder Then
: : : Set SubFolder=FolderItem.GetFolder
: : : ts.WriteLine "<p>" & SubFolder.Title & "<br>"
: : : Call RecSrch(SubFolder)
: : : ts.WriteLine "</p>"
: : ElseIf FolderItem.IsLink Then
: : : Set Link = wShell.CreateShortcut(FolderItem.Path)
: : : ts.WriteLine "<a href=""" & Link.TargetPath & """>" & FolderItem.name & "</a><br>"
: : ElseIf FolderItem.IsFileSystem Then
: : : : ts.WriteLine "<a href=""" & FolderItem.path & """>" & FolderItem.name & "</a><br>"
: : Else
: : : str=Folder.GetDetailsOf(FolderItem,-1)
: : : If InStr(str,vbCrLf) Then
: : : : arr=Split(str,vbCrLf)
: : : : ts.WriteLine "<a href=""" & arr(1) & """>" & arr(0) & "</a><br>"
: : : ElseIf InStr(str,vbLf & vbCr) Then
: : : : arr=Split(str,vbLf & vbCr)
: : : : ts.WriteLine "<a href=""" & arr(1) & """>" & arr(0) & "</a><br>"
: : : ElseIf str<>"" Then
: : : : ts.WriteLine "<a href=""" & str & """>" & FolderItem.name & "</a><br>"
: : : Else
'WScript.Echo FolderItem.path
'WScript.Echo FolderItem.name
'WScript.Echo FolderItem.IsFolder,FolderItem.IsLink,FolderItem.IsFilesystem,FolderItem.IsBrowsable
'WScript.Echo escape(str)
: : : : ts.WriteLine "<a href=""" & FolderItem.path & """>" & FolderItem.name & "</a><br>"
: : : End If
: : End If
: Next
: ts.WriteLine "</blockquote>"
End Sub

ばんのしゃーによかばんた さん 2004年 06月 30日 19時 58分 54秒

url2htmの修正です。

: : : str=Folder.GetDetailsOf(FolderItem,-1)
に改行が含まれていないときは、urlでなくファイル名をinnerTextにします。
: : : : ts.WriteLine "<a href=""" & str & """>" & FolderItem.name & "</a><br>"

制御構造が、フォルダの処理の中でサブフォルダの処理をするという、
なんかへんてこりんなので、単純な構造に変えました。
その結果、
実は、ルートのアイテムをリストしてなかったという障害

各フォルダを二回スキャンしていたという性能障害
が直りました。
ただし、性能改善の効果はそれほどではありません。10%程度です。
二回が一回になれば、相当よくなりそうなものですが、
二回目はメモリに載っているのでしょう。

――――――――――――――――――――――――――――――――――――――
'IEのお気に入りをHTMLファイルにするスクリプト

'IEのお気に入りを一つのHTMLファイルにまとめます。
'そこそこ時間がかかるので、注意。
'このままでは出力されるHTMLは非常に簡素なので、各自味付けしてください(^^;

Const strPath="favorite.htm"
'出力するHTMLファイルのパス。既存ファイルは上書きされます。
Const ssfFAVORITES = 6

Dim strHtml
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Set Shell = WScript.CreateObject("Shell.Application")

'Set Folder=Shell.NameSpace("C:\Windows\history")
'↑の場合、「履歴」をHTML化します。ただし、履歴をため込んでいる場合(999日など)は、
'死ぬほど時間がかかります。
'10000件のURLだと1時間くらいかかる…かも。
Set Folder=Shell.NameSpace(ssfFAVORITES)

WScript.Echo "ただいまから、お気に入りをHTML化します。"

Set ts=fso.CreateTextFile(strPath,True)

ts.WriteLine "<html><head><title>お気に入りリスト</title></head><body>"

Call RecSrch(Folder)

ts.WriteLine "</body></html>"
ts.Close
WScript.Echo "終了。"

Sub RecSrch(Folder)
: ts.WriteLine "<blockquote>"
: For Each FolderItem In Folder.Items
: : If FolderItem.IsFolder Then
: : : Set SubFolder=FolderItem.GetFolder
: : : ts.WriteLine "<p>" & SubFolder.Title & "<br>"
: : : Call RecSrch(SubFolder)
: : : ts.WriteLine "</p>"
: : Else
: : : str=Folder.GetDetailsOf(FolderItem,-1)
: : : If InStr(str,vbCrLf) Then
: : : : arr=Split(str,vbCrLf)
: : : : ts.WriteLine "<a href=""" & arr(1) & """>" & arr(0) & "</a><br>"
: : : ElseIf InStr(str,vbLf & vbCr) Then
: : : : arr=Split(str,vbLf & vbCr)
: : : : ts.WriteLine "<a href=""" & arr(1) & """>" & arr(0) & "</a><br>"
: : : ElseIf str<>"" Then
: : : : ts.WriteLine "<a href=""" & str & """>" & FolderItem.name & "</a><br>"
: : : End If
: : End If
: Next
: ts.WriteLine "</blockquote>"
End Sub

ばんのしゃーによかばんた さん 2004年 06月 29日 19時 50分 31秒

>いりや さん 2004年 06月 28日 00時 56分 03秒
>function Dialog1_OnQuit() { setOnQuitFlag('Dialog1_', -2) }
>function Dialog2_OnQuit() { setOnQuitFlag('Dialog2_', -2) }
>function Dialog3_OnQuit() { setOnQuitFlag('Dialog3_', -2) }

同じ名前のイベントハンドラにして、ハンドラ内で発火元オブジェクトを識別出来るようです。

Internet Explorer: Platform SDK
Understanding the Event Model
When events are fired, a special object reference - the me pointer in VBScript and this in JScript - is set to the current element firing the event.

evtCancelには、cmdCancelのHTMLInputElementオブジェクト、
ie_OnQuitにはIWebBrowser2オブジェクトが渡ります。

ポインタを辿ればイベントオブジェクトも参照/設定できるのでは。

これなら筋がよさそうです。

ばんのしゃーによかばんた さん 2004年 06月 29日 15時 04分 42秒

早速、研究成果の発表をば。
2000で確認。WebViewのみ可。98は不可。
HTMLに動的にスクリプトを組み込む例。
HTMLWindow2.ExecScriptはScriptControlの代わりに使えます。この例。
ディレクトリは適当に変更してください。
ファイルを選択すると、パスを表示します。SelectionChangedイベントを利用します。
――――――――――――――――――――――――――――――――――――――
<HTML>
<head>
<script language="VBScript">
Sub bdy_onload()
'2000 WebView Only / 98 NG
Set script=explorer.document.createElement("script")
script.language="VBScript"
script.htmlfor="FileList"
script.event="SelectionChanged"
script.text="MsgBox FileList.FocusedItem"
Call explorer.document.body.insertAdjacentElement("AfterBegin",script)
MsgBoxes explorer.document.body.parentElement.outerHTML
End Sub

Sub MsgBoxes(s)
sa=Split(s,vblf)
For k=0 To UBound(sa)
ss=ss & sa(k)
If k Mod 20=19 Then
MsgBox ss
ss=""
End If
Next
If ss<>"" Then
MsgBox ss
ss=""
End If
End Sub
</script>
</head>
<body id="bdy" onload="bdy_onload">
<iframe id="Explorer" src="file:///d:\vbs\hta" width="100%" height="100%">
</iframe>
</body>
</HTML>
――――――――――――――――――――――――――――――――――――――
<HTML>
<head>
<script language="VBScript">
Sub bdy_onload()
'2000 WebView Only / 98 NG
Call explorer.execScript("Sub FileList_SelectionChanged():MsgBox FileList.FocusedItem:End Sub","VBScript")
End Sub
</script>
</head>
<body id="bdy" onload="bdy_onload">
<iframe id="Explorer" src="file:///d:\vbs\hta" width="100%" height="100%">
</iframe>
</body>
</HTML>
――――――――――――――――――――――――――――――――――――――

ばんのしゃーによかばんた さん 2004年 06月 29日 15時 04分 01秒

>いりや さん 2004年 06月 28日 14時 03分 56秒
>FastView ウインドウ (window 変数にバインドされた
>InternetExplorer.Application オブジェクト) を閉じた時に、画
>像を表示するウインドウ (ie 変数) が開いているとき、そのウイ
>ンドウが開いたままになります。On Error Resume Next の次に
>ie.Quit もいれとくといいのかな。

これは、意図して残しています。画像を選択して表示するというシチュエーションです。

>それから、img.src として "png" もサポートするようです。
>Case "bmp","gif","jpg","art","wmf","png"

この辺はいい加減でした。:-)
ショートサーキット評価(?)なので、よく使うものから並べたほうがよいですね。

>いりや さん 2004年 06月 28日 00時 56分 03秒
>// 上記イベントハンドラを動的に作成するための一案
>// スクリプトのトップレベル、つまり、一番外のスコープで eval() グローバル
>// メソッドを実行して function オブジェクトを作成する。

私もClassの中からExecuteGlobalを出すことを考えましたが、あまり美しくないです。
こういう変な作りしか出来ないのは逆に筋のよくない試みかも、と躊躇してます。

現在、IEのイベントをWScript側と接続するのではなく、
IE側に動的にスクリプトを組み込むことを模索してます。
これなら、イベントオブジェクトが利用できますし、
また、WScript側が終了した後も、IEだけで処理が続行できます。
なんか、応用が効きそうです。:-)

>ばんのしゃーによかばんた さん 2004年 06月 28日 16時 38分 08秒
>ie.document.script.document.body.all.filelist.objectを接続するなんて、

ie.document.script.filelist.object
でもよいようです。

いりや さん 2004年 06月 29日 14時 24分 07秒

WSH/JScript で、Number 組み込みオブジェクトに自作メソッドを
追加して利用するとき一つ制約が見つかったのでお知らせします。

[ 制約内容 ]

リテラル表現に直接メソッド起動をさせようとするとインタープリ
タの構文エラーとして報告される。

[ 想定される理由 ]

数字のすぐ後のピリオドを小数点じゃないかと思って字句解析を続
けてしまっているみたい。実際には timesRepeat_ はメッセージな
のだが。

[ ワークアラウンド ]

要は字句解析でループに陥らないように表記してやればよいので、

・変数にバインドして使用する。
・括弧でくくる。3 → (3)
・new 演算子を使用する。3 → new Number(3)

[ 例 ]

Number.prototype.timesRepeat_ は、レシーバ (Number) の回数分
だけ引数の関数オブジェクトを呼び出すメソッドです。三回挨拶を
するスクリプトで説明します。

うまくいかない例:

3.timesRepeat_(function () { WScript.echo('こんにちは') });

function Number.prototype.timesRepeat_ (operation) {
    for (var i = 0; i < this; i++)
        operation();
}

失敗しそうだけどうまくいく例:

var n = 3;
n.timesRepeat_(function () { WScript.echo('こんにちは') });
(3).timesRepeat_(function () { WScript.echo('こんにちは') });
new Number(3).timesRepeat_(function () { WScript.echo('こんにちは') });

function Number.prototype.timesRepeat_ (operation) {
    for (var i = 0; i < this; i++)
        operation();
}

りな さん (selfless@e-idol.net) 2004年 06月 29日 12時 54分 57秒

先月からタレントとして活動してます。
今度某所でイベントします!
メジャーデビュー前なんだけど、応援してくれる人や友達になってくれる人募集です。
全国からメール待ってます☆彡

りな さん (selfless@e-idol.net) 2004年 06月 29日 12時 51分 01秒

先月からタレントとして活動してます。
今度某所でイベントします!
メジャーデビュー前なんだけど、応援してくれる人や友達になってくれる人募集です。
全国からメール待ってます☆彡

ばんのしゃーによかばんた さん 2004年 06月 28日 16時 38分 08秒

SelectionChangedが接続できました。
あー疲れた。これはちょっと難しいんじゃないの。
ie.document.script.document.body.all.filelist.objectを接続するなんて、
こんなの絶対分かんないよ。正にmazeです。
――――――――――――――――――――――――――――――――――――――
Option Explicit

Dim wShell
Dim fso
Dim arg
Dim Folder
Dim Window
Dim ie
Dim img
Dim FolderItem
Dim src,path
Dim OnQuit
Dim k
Dim WebView

Set wShell=CreateObject("WScript.Shell")
Set fso=CreateObject("Scripting.FileSystemObject")
Folder=""
For Each arg In WScript.Arguments
Folder=arg
Exit For
Next
Folder=fso.GetAbsolutePathName(Folder)

Set window=WScript.CreateObject("InternetExplorer.Application","IE_")
window.Navigate Folder

Set ie=WScript.CreateObject("InternetExplorer.Application","IE_")
ie.Navigate "about:blank"
Do While ie.Busy Or ie.ReadyState<>4
WScript.Sleep 100
Loop
ie.Top = 0
ie.Left = 0
ie.Width = 0
ie.Height = 0
ie.AddressBar = False
ie.MenuBar = False
ie.StatusBar = False
ie.ToolBar = False
ie.Resizable = False
ie.Document.body.scroll="no"
ie.document.body.leftMargin=0
ie.document.body.topMargin=0
ie.document.body.rightMargin=0
ie.document.body.bottomMargin=0
ie.Visible=True

Set img=ie.Document.CreateElement("img")
Call ie.document.body.insertadjacentelement("AfterBegin",img)
Set img.onload=GetRef("ViewPad")

'window.Top = 0
window.Left = ie.document.parentwindow.screen.availWidth/2
window.Width = ie.document.parentwindow.screen.availWidth/2
'window.Height = 0
window.ShowBrowserBar "{EFA24E64-B078-11D0-89E4-00C04FC9E26E}",True
window.Visible=True

'MsgBox TypeName(window.Document)
On Error Resume Next
'WScript.Echo TypeName(window.Document.script)
WebView=TypeName(window.Document.script)
On Error GoTo 0
If WebView="HTMLWindow2" Then
' WScript.Echo window.document.script.document.body.parentElement.outerHTML
Call WScript.ConnectObject(window.document.script.document.body.all.filelist.object,"SFV_")
Else
wShell.SendKeys "%(vw)"
For k=1 To 50
If TypeName(window.Document)="WebViewFolderContents" Then Exit For
If wShell.AppActivate("Internet Explorer") Then wShell.SendKeys "%y"
WScript.Sleep 100
Next
If TypeName(window.Document)="WebViewFolderContents" Then
Call WScript.ConnectObject(window.Document,"SFV_")
Else
MsgBox "Change Folder Option to Web View."
ie.Quit
End If
End If
Do
WScript.Sleep 100
If OnQuit Then WScript.Quit
Loop

Sub SFV_SelectionChanged()
If OnQuit=0 Then
On Error Resume Next
path=window.Document.FocusedItem.Path
On Error GoTo 0
If path<>src Then
Select Case LCase(fso.GetExtensionName(path))
Case "bmp","gif","jpg","art","wmf"
src=path
img.src=src
End Select
End If
End If
End Sub

Sub ViewPad()
ie.document.Title=src
ie.Width = ie.Width + img.Width - ie.document.body.clientWidth
ie.Height = ie.Height + img.Height - ie.document.body.clientHeight
If img.Width <> ie.document.body.clientWidth Or _
img.Height <> ie.document.body.clientHeight Then
ie.Width = ie.Width + img.Width - ie.document.body.clientWidth
ie.Height = ie.Height + img.Height - ie.document.body.clientHeight
End If
End Sub

Sub IE_OnQuit()
OnQuit=True
End Sub

ばんのしゃーによかばんた さん 2004年 06月 28日 16時 37分 01秒

>いりや さん 2004年 06月 27日 20時 52分 35秒
>ほー、エラーのダイアログが表示された後に処理系が Class_Terminate() を実行すると
>いうのは初めて知りました。外部資源の後始末にそれを使うのは便利ですね。

あれ、やっぱり。もしかして、読んでないのかなぁ、と思ってたら、

>ばんのしゃーによかばんた さん 2004年 05月 30日 15時 59分 28秒
>Class_Terminate二題
>こんな使い方が出来ます。
>甲案 try...finally擬に。
>乙案 エラーリカバリ、リソースパージに。
>※ エラーメッセージが出た後に、リカバリルーチンが走る。(正常終了時も走る。)
>※ リカバリルーチンの中で、エラーコード/メッセージが参照出来る。

読んでなかったのね。いりやさんが興味を持ちそうな内容だったのに。

いりや さん 2004年 06月 28日 14時 03分 56秒

ばんのしゃーによかばんたさん、

| エクスプローラのフォルダビューの代わりに、ShellNameSpaceを使ってみました。
| ShellNameSpaceはConnectObjectでFavoritesSelectionChangeが接続できます。
| 画像はスクリーンサイズを超えるとスクリーンに収まるように縮小します。

面白いアプリケーションです。

気のついたところを。

FastView ウインドウ (window 変数にバインドされた
InternetExplorer.Application オブジェクト) を閉じた時に、画
像を表示するウインドウ (ie 変数) が開いているとき、そのウイ
ンドウが開いたままになります。On Error Resume Next の次に
ie.Quit もいれとくといいのかな。

それから、img.src として "png" もサポートするようです。

Case "bmp","gif","jpg","art","wmf","png"

で、このように追加しました。

ヒナ さん (hina_hina@vjp.jp) 2004年 06月 28日 13時 09分 54秒

おはつです!22のひなです。
わたし、昔お店で働いていたからテクにはちょっと自信ありますよ♪
でも新しいことにも興味あり!やっぱ向上心は大切でしょ(笑)
では、お返事まってまーす。

kkkkk さん 2004年 06月 28日 11時 41分 40秒

はじめまして。
スクリプトファイルについて聞きたいのですが、あるゲームを起動しようとすると「システムファイルをアップデートします。」とでで、OKしかなくて、OKをクリックすると「スクリプトファイルを開けません。」とでます。どうしたらよいのでしょうか?教えて頂けませんか?

kkkkk さん 2004年 06月 28日 11時 40分 41秒

はじめまして。
スクリプトファイルについて聞きたいのですが、あるゲームを起動しようとすると「システムファイルをアップデートします。」とでで、OKしかなくて、OKをクリックすると「スクリプトファイルを開けません。」とでます。どうしたらよいのでしょうか?教えて頂けませんか?

いりや さん 2004年 06月 28日 00時 56分 03秒

これまで分かったことをもとに、vagabond さんのスクリプトをベースに、ばん
のしゃーによかばんたさんのコメントを盛り込んで、三つのダイアログ (を模し
たウインドウ) をあつかうスクリプトを書いてみました。

ポイントは「onQuit フラグを tristate (三つの状態をもつ) にして、外部要因
でウインドウの資源が解放された場合を知ることができる」ようにしたところで
す。

finalization のタイミングをプログラマが陽に与えているところはかわりあり
ません。また、前の投函で

| いまのところ、放送の内容がこの一つしか思いつかないので、放送を受信する仕掛けと
| して、onQuit フラグを使用し、並行してもう少し一般的で包括的な枠組みがこさえられ
| ないか検討したいところです。

と書きましたがこちらは取り組んでいる途中です。

あと、かいていて気づいたところです。
今後の課題ですね。

・ダイアログの仕様をパラメータとして外に出すやり方についてはまだまだ検討の
 余地あり。(いまはほとんどハードコーディングで、ウインドウのタイトルと
 表示座標しか外だししていません。)

・InternetExplorer.Application オブジェクトのイベントハンドラもハードコー
 ディングしている。このあたりもなるべく外だしにしたい。

・Dynamic HTML Object Model 側のイベントハンドラで WScript.echo() を実行
 していると、そこでスクリプトホスト側の実行がブロックされてしまう。(ス
 クリプトの★1, ★2 の箇所) これがなぜ具合が悪いかというとブロックされ
 ている間 mainLoop() もブロックされてしまい、複数のウインドウが並行動作
 する、という前提が崩れてしまうから。

[ WSH/JScript ]

debug = false にすれば、デバッグ情報の表示は抑制できます。(2 箇所)


var dialogArray = new Array(
    { window: new DialogWindow('Dialog1_', 'ダイアログ1', 10, 10),
     prefix: 'Dialog1_',
     onQuit: false,
     isFinalized: false },
    { window: new DialogWindow('Dialog2_', 'ダイアログ2', 315, 10),
     prefix: 'Dialog2_',
     onQuit: false,
     isFinalized: false },
    { window: new DialogWindow('Dialog3_', 'ダイアログ3', 620, 10),
     prefix: 'Dialog3_',
     onQuit: false,
     isFinalized: false }
);

function Dialog1_OnQuit() { setOnQuitFlag('Dialog1_', -2) }
function Dialog2_OnQuit() { setOnQuitFlag('Dialog2_', -2) }
function Dialog3_OnQuit() { setOnQuitFlag('Dialog3_', -2) }

// 上記イベントハンドラを動的に作成するための一案
//
// スクリプトのトップレベル、つまり、一番外のスコープで eval() グローバル
// メソッドを実行して function オブジェクトを作成する。

// eval('var %1OnQuit = new Function(\'setOnQuitFlag("%1", -2)\');'.replace(/%1/g, 'Dialog1_'));
// eval('var %1OnQuit = new Function(\'setOnQuitFlag("%1", -2)\');'.replace(/%1/g, 'Dialog2_'));
// eval('var %1OnQuit = new Function(\'setOnQuitFlag("%1", -2)\');'.replace(/%1/g, 'Dialog3_'));

debug = true;
dialogArray.do_(function (each) { each.window.visible = true });
mainLoop();

function mainLoop () {
    while (true) {
        WScript.sleep(0.1 * 1000);
        var closedDialogArray = dialogArray.select_(function (each) { return each.onQuit == true });
        var finilizeBlock = function (each) {
            if (!each.isFinalized) {
                debug && WScript.echo('終了〜: ' + each.prefix);
                each.isFinalized = true;
                each.window.quit();
            }
        }
        closedDialogArray.do_(finilizeBlock);
        var openDialogArray = dialogArray.select_(function (each) { return each.onQuit == false });
        if (openDialogArray.length == 0) {
            debug && WScript.echo('終了〜: 全体');
            WScript.quit();
        }
        // Note that dialog.isFinalized doesn't change when dialog.onQuit changes with -2 because
        // isFinalized property is only used in order to explicitly finalize the external resource,
        // the InternetExplorer.Application object in this case.
    }
}

function setOnQuitFlag(prefix, tristateValue) {
    var anArray = dialogArray.select_(function (each) { return each.prefix == prefix });
    if (anArray.length == 1) {
        var dialog = anArray[0];
        dialog.onQuit = tristateValue;
    }
}

function DialogWindow(prefix, title, left, top) {
    var e = WScript.createObject('InternetExplorer.Application', prefix);
    var wait = function () {
        while (e.busy || e.readyState != 4)
            WScript.sleep(0.1 * 1000);
    }
    var navigate = function () {
        if (arguments.length == 0) {
            e.navigate('about:blank');
            wait();
        }
        if (arguments.length == 1 && typeof(arguments[0]) == 'string') {
            e.navigate(arguments[0]);
            wait();
        }
    }
    var initialize = function () {
        navigate();
        e.document.write(new Array(
            '<html>',
            '<head></head>',
            '<body>',
            '<table>',
                '<tr><td>ユーザー名</td>',
                    '<td><input type=textbox name=UserID></td></tr>',
                '<tr><td>パスワード</td>',
                    '<td><form id=form1><input type=password name=Password></form></td></tr>',
            '</table>',
            '<br><br>',
            '<input type=button value=" OK " class=ok id=cmdOK>',
            '<input type=button value="CANCEL" class=cancel id=cmdCancel>',
            '</body>',
            '</html>').join(''));
        e.document.close();
        wait();

        var w = e.document.parentWindow;
        w.moveTo(left, top);
        w.resizeTo(300, 200);
        w.document.title = title;
        w.document.body.scroll='no';
        w.document.bgcolor='MENU';

        e.toolbar = false;
        e.statusbar = false;
        e.menubar = false;
        e.resizable = false;
    }
    var onClickHandler_cmdOK = function () {
        var userID = new String(e.document.parentWindow.document.all.UserID.value);
        var password = new String(e.document.parentWindow.document.all.Password.value);
        WScript.echo('You clicked OK. Value: ' + userID + ' ' + password); // ★1
        setOnQuitFlag(prefix, true);
    }
    var onClickHandler_cmdCancel = function () {
        WScript.echo('You clicked Cancel.'); // ★2
        setOnQuitFlag(prefix, true);
    }
    var registerHandlers = function () {
        var w = e.document.parentWindow;
        w.document.all.cmdOK.onclick = onClickHandler_cmdOK;
        w.document.all.cmdCancel.onclick = onClickHandler_cmdCancel;
        w.document.all.form1.onsubmit = onClickHandler_cmdOK;
    }
    initialize();
    registerHandlers();
    return e;
}

//
// Array
//

function Array.prototype.do_(operation) {
    for (var i = 0; i < this.length; i++)
        operation(this[i]);
}

function Array.prototype.select_(discriminator) {
    var anArray = new Array();
    this.do_(function (each) { if (discriminator(each)) anArray.push(each) });
    return anArray;
}

ばんのしゃーによかばんた さん 2004年 06月 27日 21時 38分 49秒

>管理人むたぐち さん 2004年 06月 14日 17時 50分 37秒
>SelectionChangedは、WScript.ConnectObjectが使えない(どこかで
>仕様だとかバグだとか聞いた気がします)ので、
>多分どうしようもないでしょう。

これですが、Webビューにすると、ConnectObjectが可能になり、
SelectionChangedが拾えるようになりました。

で、今度は、
スクリプトからWebビューに切り替えるには、どうすればよいのでしょうか。

※奥深いと言うか、きりがないと言うか、だからおもしいんですが。。。

いりや さん 2004年 06月 27日 20時 52分 35秒

vagabond さん、

| 今回は、Enterした時も、OKを押した時と動きを同じにしたいので、
| Set .document.all.form1.onsubmit = GetRef("evtOK")
| としました。これで解決です。

うまくいったようでなによりです。Dynamic HTML Object Model の世界は色々と奥が深
くプログラミングの可能性が広がっていますので、いろいろと調べる価値があります。


ばんのしゃーによかばんたさん、

| これで、WScript.Quitの延長で資源解放してくれます。
| メイン処理でエラーが起きたときも、エラーダイアログを出した後に資源解放してくれます。
| これが、すばらしいんですね。IE/Excelなどを使ったとき、エラーで残るが大問題ですから。

ほー、エラーのダイアログが表示された後に処理系が Class_Terminate() を実行すると
いうのは初めて知りました。外部資源の後始末にそれを使うのは便利ですね。

今回のプログラミングの課題を整理すると、

(1) 利用者が InternetExplorer.Application オブジェクトを不要に思ったときには、
  必ずそのオブジェクトも解放されてほしい。
(2) 利用者以外もそのオブジェクトを不要と判断して解放することがあって、そういう
  事態を利用者が知る手立てがほしい。

これは SRA の青木さんが

  http://www.sra.co.jp/people/aoki/SmalltalkTextbookJ/textbook48.html

でおっしゃっている WeakReference & Finalization のテーマですね。


(1) については、最初に書いた JScript スクリプトは、finalization のタイミングを
onQuit フラグで陽に与えて、外部資源の解放を d.quit() (具体的には
InternetExplorer.Ap plication>>quit()) で実現している。

これだとプログラマが finalization のタイミングを全部洗い出してそこに onQuit フ
ラグをたてるロジックを組み込まねばならないので、プログラマへの精神的な負担が大
きい。

でも、ばんのしゃーによかばんたさんの Class_Terminate() は、洗い出しをせずとも
VBScript のインタープリタ (wscript.exe + vbscript.dll) のガベジコレクタに一任で
きるので、プログラマはその負担から解放されます。

さらに「エラーダイアログを出した後に資源解放してくれ」るのは特徴的ですね。エラー
・ダイアログが表示された後の振る舞いをプログラマに (Class_terminate() を通して)
解放してくれているわけですから。

JScript のインタープリタ (wscript.exe + jscript.dll) には finalization のメカニ
ズムは組み込まれていません。もっとも、エラーを制御する、という意味では、

function mainLoop (d) {
    while (true) {
        WScript.sleep(0.1 * 1000);
        if (onQuit) {
            try {
                d.quit();
            } catch (error) {
                // throw error;
            } finally {
                WScript.quit();
            }
        }
    }
}

という風に、d.quit() でエラーが発生しても実行を継続させることは出来ます。が、あ
くまで局所解でしかないですね。


(2) については、考えどころです。青木さんの解説では、

| 「しめくくり(Finalization)」とは、映画で有名なターミネータがやってくることで、
| ガベジコレクションにかかる瞬間です。もし、丙くんがコレクションの依存物であると、
| 乙くんの消滅と時を同じくして「乙くんが死にました」という放送が入ってきます。

という点に着目して、その放送が入ってきたら、丙が死体を nil にするメッセージ (火
葬) を送っています。

ばんのしゃーによかばんたさんの onQuit フラグを tristate にして -2 をセットする
のは「乙くん (InternetExplorer.Application オブジェクト) が死にました」と放送し、
mainLoop() で onQuit == true かどうかを判断するのは放送を受信していることに相当
するんだとおもいます。

いまのところ、放送の内容がこの一つしか思いつかないので、放送を受信する仕掛けと
して、onQuit フラグを使用し、並行してもう少し一般的で包括的な枠組みがこさえられ
ないか検討したいところです。例えば Smalltalk のプラガブルアダプタ (PluggableAdaptor)
なんかお手本としたいですね。

ばんのしゃーによかばんた さん 2004年 06月 27日 17時 53分 25秒

ファイルをドロップすると、ファイル名を表示する、HTMLとVBScritのプロトタイプです。
いろいろ応用が効くのではないでしょうか。クリップボードへのコピーとか。
ここでは、ステータスバーを使用していますが、OLEDragDropが使えれば何でもよいです。
マウスポインタがショートカット時のものになります。ByRef As 型が使えないため、
effectを変更しても反映されないのでしょう。
OLEDragDropが使えるコモンコントロールを使うにはVBの開発環境が必要です。
VB5CCEでもよいので、何度も言うようですが、持ってないひとはDownLoadすべし。
――――――――――――――――――――――――――――――――――――――
<html><head>
<script language=vbscript>
'Private Sub StatusBar1_OLEDragDrop(Data As ComctlLib.DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)
Private Sub StatusBar1_OLEDragDrop(Data, Effect, Button, Shift, x, y)
For i = 1 To Data.files.Count
MsgBox (Data.files.Item(i))
Next
End Sub
'Private Sub StatusBar1_OLEDragOver(Data As ComctlLib.DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer)
Private Sub xStatusBar1_OLEDragOver(Data, Effect, Button, Shift, x, y, State)
effect=1
End Sub
</script>
</head><body>
<object id="StatusBar1" classid="CLSID:8E3867A3-8586-11D1-B16A-00C0F0283628" width="100%" height="100%">
<PARAM NAME="OLEDropMode" VALUE="1">
</object></body></html>
――――――――――――――――――――――――――――――――――――――
Set ie=CreateObject("InternetExplorer.Application")
ie.Navigate "res://mshtml.dll/blank.htm"
Do While ie.Busy Or ie.ReadyState<>4
WScript.Sleep 100
Loop
ie.Visible=True
Set status=ie.Document.CreateElement("object")
status.classid="CLSID:8E3867A3-8586-11D1-B16A-00C0F0283628"
Call ie.document.body.insertadjacentelement("AfterBegin",status)
'WScript.Echo ie.document.body.parentElement.outerHTML
status.width="100%"
status.height="100%"
status.OLEDropMode=1
Call WScript.ConnectObject(status.object,"StatusBar1_")
ie.statustext="Connected"
Do While ie.visible
WScript.Sleep 100
Loop
WScript.Quit

'Private Sub StatusBar1_OLEDragDrop(Data As ComctlLib.DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)
'Private NOP
Sub StatusBar1_OLEDragDrop(Data, Effect, Button, Shift, x, y)
For i = 1 To Data.files.Count
MsgBox (Data.files.Item(i))
Next
End Sub
'Private Sub StatusBar1_OLEDragOver(Data As ComctlLib.DataObject, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer)
Sub StatusBar1_OLEDragOver(Data, Effect, Button, Shift, x, y, State)
effect=1
End Sub
――――――――――――――――――――――――――――――――――――――

管理人むたぐち さん 2004年 06月 26日 17時 39分 46秒

@IT:特集 .NET完全対応で生まれ変わったDelphi 8
http://www.atmarkit.co.jp/fdotnet/special/delphi8/delphi8_01.html

Delphiが .NETに対応ということです。
Personal版がなくなったのが残念…。


To: ばんのしゃーによかばんた さん

> >To: クッキー さん
> >> 例えば、フォルダ内でファイルを縮小表示させた場合、
> >> 全ファイルのプレビュー表示が出てきますが、この表示を
> >> 拡大するのはどこを書き換えればいいのでしょうか?

実はWinXPではTweakUIでプレビューサイズを変更できたりします。

ばんのしゃーによかばんた さん 2004年 06月 26日 17時 17分 44秒

エクスプローラのフォルダビューの代わりに、ShellNameSpaceを使ってみました。
ShellNameSpaceはConnectObjectでFavoritesSelectionChangeが接続できます。
画像はスクリーンサイズを超えるとスクリーンに収まるように縮小します。

ところで、ファイルを選択したら、画像のWindowを手前に表示し、しかも、
フォルダのWindowにfocusを持たせる。ということは出来ないでしょうか。
――――――――――――――――――――――――――――――――――――――
Option Explicit

Dim fso
Dim arg
Dim Folder
Dim Window
Dim ie
Dim img
Dim FolderItem
Dim src
Dim OnQuit
Dim WidthMargin,HeightMargin
Dim screenWidth,screenHeight
Dim nsc

Set fso=CreateObject("Scripting.FileSystemObject")
Folder=""
For Each arg In WScript.Arguments
Folder=arg
Exit For
Next
Folder=fso.GetAbsolutePathName(Folder)

Set window=WScript.CreateObject("InternetExplorer.Application","IE_")
window.Navigate "res://mshtml.dll/blank.htm"
Do While window.Busy Or window.ReadyState<>4
WScript.Sleep 100
Loop

Set ie=WScript.CreateObject("InternetExplorer.Application","IE_")
ie.Navigate "about:blank"
Do While ie.Busy Or ie.ReadyState<>4
WScript.Sleep 100
Loop
ie.Top = 0
ie.Left = 0
ie.AddressBar = False
ie.MenuBar = False
ie.StatusBar = False
ie.ToolBar = False
ie.Resizable = False
ie.Document.body.scroll="no"
ie.document.body.leftMargin=0
ie.document.body.topMargin=0
ie.document.body.rightMargin=0
ie.document.body.bottomMargin=0
WidthMargin=ie.Width - ie.document.body.clientWidth
HeightMargin=ie.Height - ie.document.body.clientHeight
screenWidth=ie.document.parentwindow.screen.availWidth
screenHeight=ie.document.parentwindow.screen.availHeight
'WScript.Echo WidthMargin,HeightMargin,screenWidth,screenHeight
ie.Width = 0
ie.Height = 0
ie.Visible=True

Set img=ie.Document.CreateElement("img")
Call ie.document.body.insertadjacentelement("AfterBegin",img)
Set img.onload=GetRef("ViewPad")

'window.Top = 0
window.Left = screenWidth*3/4
window.Width = screenWidth/4
'window.Height = 0
window.AddressBar = False
window.Document.body.scroll="no"
window.MenuBar = False
window.ToolBar = False
window.Document.title="FastView - " & Folder

Set nsc=window.Document.CreateElement("object")
nsc.classid="clsid:55136805-B2DE-11D1-B9F2-00A0C98BC547"
call window.document.body.insertadjacentelement("AfterBegin",nsc)
nsc.width="100%"
nsc.height="100%"
Call WScript.ConnectObject(nsc.object,"NSC_")
nsc.SetRoot Folder
window.Visible=True
Do While Not OnQuit
WScript.Sleep 100
Loop
On Error Resume Next
window.Quit
WScript.Quit

Sub NSC_FavoritesSelectionChange(cItems, hItem, strName, strUrl, cVisits, strDate, fAvailableOffline)
'WScript.Echo cItems,strName,strUrl
If strUrl<>src Then
Select Case LCase(fso.GetExtensionName(strUrl))
Case "bmp","gif","jpg","art","wmf"
src=strUrl
img.src=src
End Select
End If
End SUb

Sub ViewPad()
Dim imgWidth,imgHeight
Dim wx,hx
Call img.removeAttribute("Width",0)
Call img.removeAttribute("Height",0)
ie.document.Title=src
'WScript.Echo img.Width,screenWidth,img.Height,screenHeight
imgWidth=img.Width
imgHeight=img.Height
wx=(screenWidth - WidthMargin)/imgWidth
hx=(screenHeight - HeightMargin)/imgHeight
If wx>hx Then wx=hx
If wx>=1 Then
ie.Width = imgWidth + WidthMargin
ie.Height = imgHeight + HeightMargin
Else
imgWidth=imgWidth*wx
imgHeight=imgHeight*wx
img.Width=imgWidth
img.Height=imgHeight
ie.Width = imgWidth + WidthMargin
ie.Height = imgHeight + HeightMargin
End If
End Sub

Sub IE_OnQuit()
OnQuit=True
End Sub
――――――――――――――――――――――――――――――――――――――

同じようなことを考えるひとは他にもいらっしゃるようで、
>管理人むたぐち さん (mutaguchi@roy.hi-ho.ne.jp) 2002年 04月 09日 23時 20分 09秒
>To: クッキー さん
>> 例えば、フォルダ内でファイルを縮小表示させた場合、
>> 全ファイルのプレビュー表示が出てきますが、この表示を
>> 拡大するのはどこを書き換えればいいのでしょうか?
>WinMEは2000に比べて縮小表示が小さくなって使いにくいですよね。
>でも、残念ながら無理です。というのも、縮小表示の機能は、HTMLでやっているわけではなく、
>ファイルリストコントロール(ShellFolderView)が実現しているからです。
>あいにく、サイズを調整するメソッド等は、ないようです。
>私は、ファイルリストコントロールを使わずに、HTMLの機能を使って、フォルダ内
>画像プレビューモードをつけてしまおうとか考えていたりします。
>できるかどうかわかりませんけどね。

私も、Web表示のhttへの組み込みを試みましたが、フォルダごとに設定が必要で、
また、フォルダを移るとhttが再起動するので、やめました。
外部から操るほうが、向いています。

ばんのしゃーによかばんた さん 2004年 06月 26日 17時 16分 48秒

>vagabond さん 2004年 06月 25日 10時 46分 02秒
>いりやさん
>Set .document.all.form1.onsubmit = GetRef("evtOK")

.document.body.scroll="no"
.document.bgcolor="MENU"
を追加。
あと、borderあたりに隙間が空いて透けて見えるのはどうすればよいのでしょう。

ばんのしゃーによかばんた さん 2004年 06月 26日 15時 03分 48秒

訂正。 Newが抜けてました。
Set AtExit=New OnScriptTerminate

>凡児 さん 2004年 06月 21日 11時 26分 28秒
>古いDOSのアプリをW2KやXPで全面表示起動させたい場合はどうしたら
>良いのでしょうか?
>W98だとアプリやバッチのプロパテイで直接画面サイズの変更が出来
>ましたがW2KやXPは見当たりません。 まず c:\winnt\system32\cmd.exe
>のプロパテイ・画面サイズを変えておき、まずシェルで全面白黒画面を
>立ち上げ、そこから手動でアプリなりバッチを起動すると見事に全画面
>になりますが、ShellRunで起こすと元に戻ってしまいます。

同じだと思うんですが。
例えば、FD.COMのプロパティを設定すればFD.PIFが出来て、
そこに全画面表示を指定する。FD.PIFをwShell.Runする。
違ってます?

ばんのしゃーによかばんた さん 2004年 06月 25日 19時 41分 07秒

>いりや さん 2004年 06月 24日 22時 53分 44秒
> | VBScriptならClassを使って、Class_Terminate()で資源解放すればOK。:-)
> 今回のようなスクリプトだと Class_Terminate() にどのように書くといいん
> でしょうね。

単純にe.QuitをClass_Terminate()に持っていけばよいのです。

Class OnScriptTerminate
Class_Terminate()
If OnQuit<>-2 Then e.Quit
End Sub
End Class
これだけです。あとはメインのほうで、
Set AtExit=OnScriptTerminate
などと設定しておきます。
これで、WScript.Quitの延長で資源解放してくれます。
メイン処理でエラーが起きたときも、エラーダイアログを出した後に資源解放してくれます。
これが、すばらしいんですね。IE/Excelなどを使ったとき、エラーで残るが大問題ですから。

もっと本格的にClass化するなら
Class Dialog
Public e
Class_Initialize()
Set e=WScript.CreateObject(...)

End Sub
Class_Terminate()
If OnQuit<>-2 Then e.Quit
End Sub
End Class
のようになるのでしょうが、
残念ながら、IEなどのEventのSubはClassの中に書けないようです。
ということはEventのSubで複数インスタンスを区別できない。

芳子 さん (jpk7136@jpcom.jp) 2004年 06月 25日 12時 14分 34秒



はじめまして、初めて書かせて頂きます。
私は結婚もしていてとても幸せです!
ですので家庭はこわしたくないので絶対に
お互いの生活には立ち入らない約束を
守れる人メールください。


ばんのしゃーによかばんた さん 2004年 06月 25日 11時 54分 05秒

>ばんのしゃーによかばんた さん 2004年 06月 24日 19時 09分 49秒
>むたぐちさん作、IEのお気に入りをHTMLファイルにするスクリプト

人生いろいろ、改行文字もいろいろ。

LF+CRもあるようです。(98、2000)

――――――――――――――――――――――――――――――――――――――
'IEのお気に入りをHTMLファイルにするスクリプト

'IEのお気に入りを一つのHTMLファイルにまとめます。
'そこそこ時間がかかるので、注意。
'このままでは出力されるHTMLは非常に簡素なので、各自味付けしてください(^^;

Const strPath="C:\favorite.htm"
'出力するHTMLファイルのパス。既存ファイルは上書きされます。
Const ssfFAVORITES = 6

Dim strHtml
Set Fs = WScript.CreateObject("Scripting.FileSystemObject")
Set Win = WScript.CreateObject("Shell.Application")

'Set objFolder=Win.NameSpace("C:\Windows\history")
'↑の場合、「履歴」をHTML化します。ただし、履歴をため込んでいる場合(999日など)は、
'死ぬほど時間がかかります。
'10000件のURLだと1時間くらいかかる…かも。
Set objFolder=Win.NameSpace(ssfFAVORITES)

msgbox "ただいまから、お気に入りをHTML化します。"

Set ts=Fs.CreateTextFile(strPath,True)

ts.WriteLine "<html><head><title>お気に入りリスト</title></head><body>"

Call RecSrch(objFolder)

ts.WriteLine "</body></html>"
ts.Close
msgbox "終了。"

Sub RecSrch(obj)
: ts.WriteLine "<blockquote>"
: For Each objItem In obj.Items
: : If objItem.IsFolder Then
: : : Set objSubFolder=objItem.GetFolder
: : : ts.WriteLine "<p>" & objSubFolder.Title & "<br>"
: : : For Each objSubItem In objSubFolder.Items
: : : : If objSubItem.IsFolder=False Then
: : : : : str=objSubFolder.GetDetailsOf(objSubItem,-1)
: : : : : If InStr(str,vbCrLf) Then
: : : : : : arr=Split(str,vbCrLf)
: : : : : : ts.WriteLine "<a href=""" & arr(1) & """>" & arr(0) & "</a><br>"
: : : : : ElseIf InStr(str,vbLf & vbCr) Then
: : : : : : arr=Split(str,vbLf & vbCr)
: : : : : : ts.WriteLine "<a href=""" & arr(1) & """>" & arr(0) & "</a><br>"
: : : : : ElseIf str<>"" Then
: : : : : : ts.WriteLine "<a href=""" & str & """>" & str & "</a><br>"
: : : : : End If
: : : : End If
: : : Next
: : : ts.WriteLine "</p>"
: : : Call RecSrch(objSubFolder)
: : End If
: Next
: ts.WriteLine "</blockquote>"
End Sub
――――――――――――――――――――――――――――――――――――――

さて、本題に戻って。(ここまでは、前振り。)

>ふみふみ さん 2004年 05月 07日 16時 43分 42秒
>Download のコーナーから url2htm を愛用させて頂いております。
>この Script を IE の履歴(History) を書き出すようにして利用させて頂いておりますが、
>9x系のOS では問題なく動作するのですが、NT5.x系のOS では正常に動作しなくて困って>おります。
>Set objFolder=Folder.NameSpace("shell:History")
>としてみても "obj がない" 旨の Error Alart が表示されます。

は、これで動きませんか。

もし、動かないようでしたら、エラーの具体的で正確な情報を。
少なくとも、エラーのコード、メッセージ、ソース、行番号と実際の行の特定は必須です。

可能ならば、
出力ファイルの末尾を見て、どこまで処理出来て、何を処理しようとしてエラーになったか。

もし、データに依存しているようなら、
: : : : : str=objSubFolder.GetDetailsOf(objSubItem,-1)
のあとに、
wscript.echo escape(str)
を入れて、
cscript url2htm.vbs > file
で実行して、どういうデータか調べるとよいかも知れません。

vagabond さん 2004年 06月 25日 10時 46分 02秒

いりやさん

レス遅くなりました。
なるほど、onsubmitで定義すればいいんですね〜〜
今回は、Enterした時も、OKを押した時と動きを同じにしたいので、
Set .document.all.form1.onsubmit = GetRef("evtOK")
としました。これで解決です。
ありがとうございました!


いりや さん 2004年 06月 24日 22時 53分 44秒

ばんのしゃーによかばんたさん、

| VBScriptならClassを使って、Class_Terminate()で資源解放すればOK。:-)

今回のようなスクリプトだと Class_Terminate() にどのように書くといいん
でしょうね。

| IEをGUI(X buttonなど)でQuitした後で、またd.quit()してエラーになりそう。

ありゃ。そうですね。タイミング・イシューで d に束縛されているリファレ
ンスが無効となるエラーの発生を確認をしました。

[ 再現手段 ]

if (onQuit) { 配下に

            WScript.echo('はい');
            d.quit();
            WScript.quit();

と echo メソッドを入れておく。スクリプトを実行し、ウインドウが表示さ
れたら、
  (1) 閉じる (Alt + F4) メニューを選ぶ
  (2) ×ボタンを押す
のどちらかを実行する。そして 'はい' ウインドウが表示されたら、しばら
くしてから OK ボタンを押下する。

そうすると、

行:   16
エラー: 起動されたオブジェクトはクライアントから切断されました。
コード: 80010108
ソース: (null)

と出てきます。(16 行目は d.quit(); です)

| 例えば、OnQuitをtristateにして、Dialog_OnQuitではonQuit = -2にして、
| if (onQuit==true) d.quit();
| とかする。

そうですね。

Dialog_OnQuit イベントハンドラが実行された後はもう d に束縛されている
リファレンスはさわっちゃいかん、ということを伝えてあがえる必要があり
ますから onQuit にそれを乗せる方法は一案だと思います。

ばんのしゃーによかばんた さん 2004年 06月 24日 22時 47分 26秒

>管理人むたぐち さん 2004年 06月 24日 19時 42分 19秒
>100万行ほどあるテキストファイルを出力する処理で、
>処理結果を一旦変数に入れてから後でまとめてWriteしてたんですが、
>それを1行ごと処理してWriteLineすると、めちゃくちゃ速くなりました。
>文字列を&で繋ぐ処理は本当に重いんですねえ。

問題の本質は、メモリで処理することが悪いのではなく、
数(n)に非線形な処理を作ってはいけない、ということです。
for 100万行
str=str & line
next
は、1+2+3+ + + 100万=n*(n+1)/2
ですから、n**2のオーダ、つまり線型を超えています。
どんなに1の処理が軽かろうと、そのn**2倍は本当に重たくなります。

また、1、2、3、、、というような逓増するメモリサイズの取り直しの繰り返しは、
メモリ領域のフラグメンテーションを起こす典型的なパターンです。
したがって、メモリ不足を起こして、性能低下を招くか、
ガーベジコレクションが頻繁に走って、性能低下を招くか、
どちらかです。

for 100万行
write line
next
はwrite1回の処理が多少重たかろうが、線型ですから、
処理内容に応じた常識的に妥当な性能になります。

ソフト開発元として顧客対応をした経験では、
数に線型な処理時間は、ユーザが予想可能で、多少性能に不満でも、
まだ我慢して貰えることが多いです。
しかし、非線形となると、「絶対に」許して貰えません。

ばんのしゃーによかばんた さん 2004年 06月 24日 21時 00分 11秒

>いりや さん 2004年 06月 24日 02時 27分 25秒
>ちなみに書いていて、今後の課題だな〜と思ったのは、InternetExplorer.Application
>オブジェクトを複数つかって複数のウインドウを表示するときに、それらを最終
>的に解放するタイミングを制御することでしょうか。いまは onQuit 広域変数を
>解放タイミングを伝えるフラグに利用しているのですがこれだと一枚のウインド
>ウしか対応しません。

VBScriptならClassを使って、Class_Terminate()で資源解放すればOK。:-)

>        if (onQuit) {
>            // onQuit が d および d に付随する資源を解放する引き金とする。
>            // d は InternetExplorer.Application オブジェクトなので quit()
>            // メソッドを明示して呼ばないと対象ウインドウ (外部資源) を解放
>            // しない。そのため、wscript.exe 処理系の実行を終了する前に、
>            // quit() メソッドを呼び、資源の解放を依頼する。
>            d.quit();
>            WScript.quit();
>        }
>    }
>}
>
>function Dialog_OnQuit() {
>    onQuit = true;
>}
>
>function Dialog () {
>    var e = WScript.createObject('InternetExplorer.Application', 'Dialog_');

IEをGUI(X buttonなど)でQuitした後で、またd.quit()してエラーになりそう。
例えば、OnQuitをtristateにして、Dialog_OnQuitではonQuit = -2にして、
if (onQuit==true) d.quit();
とかする。

いりや さん 2004年 06月 24日 20時 32分 13秒

むたぐちさん、

> 文字列を&で繋ぐ処理は本当に重いんですねえ。

文字列の連接オペレータを使用するときは要注意です。

というのは、空間効率も時間効率もわるいプログラミングがすぐ出
来てしまうからなんです。ですが、そこになかなか気づかない。わ
たしは三年前のあるとき Smalltalk でプログラミングをしていて
見事にハマっちゃいました。

・きっかけ

http://www.sra.co.jp/smalltalk/SML/archives/2001-February/004903.html
http://www.sra.co.jp/smalltalk/SML/archives/2001-February/004904.html
http://www.sra.co.jp/smalltalk/SML/archives/2001-February/004911.html
http://www.sra.co.jp/smalltalk/SML/archives/2001-February/004912.html

・まとめ

http://www.sra.co.jp/smalltalk/SML/archives/2001-March/004957.html
http://www.sra.co.jp/smalltalk/SML/archives/2001-March/004958.html
http://www.sra.co.jp/smalltalk/SML/archives/2001-March/004959.html
http://www.sra.co.jp/smalltalk/SML/archives/2001-March/004960.html

いりや

管理人むたぐち さん 2004年 06月 24日 19時 42分 19秒

返信は前ページから。


To: oo さん

> それだと、rsh自体の終了コード(リモートホストと通信できないとか、ユーザー権限が無いとかなら非0で、リモートでスクリプトが起動できれば0)しかわかりません。

それもそうですね、失礼しました。


そしてこのページ。


To: たね さん

ASPはよく分かりませんので、他の方のフォローを待ってください。
…最近こんなのばっかりですみません。


To: ばんのしゃーによかばんた さん

> これがこんなに遅いのは、メモリ上の文字列処理のためです。
> 性能問題でよくある間違いのひとつが、IOよりメモリの処理が速い、という思い込みです。
> メモリ処理をIOに変えるだけで随分と速くなります。

改良ありがとうございます。

実はこの思い込み、偶然ですがごく最近、思い込みだったことに気づきました。
100万行ほどあるテキストファイルを出力する処理で、
処理結果を一旦変数に入れてから後でまとめてWriteしてたんですが、
それを1行ごと処理してWriteLineすると、めちゃくちゃ速くなりました。
文字列を&で繋ぐ処理は本当に重いんですねえ。

ちなみに、.NET Frameworkには、この問題を解消するための
StringBuilderクラスというのがあります。

@IT:.NET TIPS 文字列を連結するには?
http://www.atmarkit.co.jp/fdotnet/dotnettips/029strcat/strcat.html

ばんのしゃーによかばんた さん 2004年 06月 24日 19時 09分 49秒

むたぐちさん作、IEのお気に入りをHTMLファイルにするスクリプト

>'そこそこ時間がかかるので、注意。
>'↑の場合、「履歴」をHTML化します。ただし、履歴をため込んでいる場合(999日など)は、
>'死ぬほど時間がかかります。
>'10000件のURLだと1時間くらいかかる…かも。

これがこんなに遅いのは、メモリ上の文字列処理のためです。
性能問題でよくある間違いのひとつが、IOよりメモリの処理が速い、という思い込みです。
メモリ処理をIOに変えるだけで随分と速くなります。

――――――――――――――――――――――――――――――――――――――
'IEのお気に入りをHTMLファイルにするスクリプト

'IEのお気に入りを一つのHTMLファイルにまとめます。
'そこそこ時間がかかるので、注意。
'このままでは出力されるHTMLは非常に簡素なので、各自味付けしてください(^^;

Const strPath="C:\favorite.htm"
'出力するHTMLファイルのパス。既存ファイルは上書きされます。
Const ssfFAVORITES = 6

Dim strHtml
Set Fs = WScript.CreateObject("Scripting.FileSystemObject")
Set Win = WScript.CreateObject("Shell.Application")

'Set objFolder=Win.NameSpace("C:\Windows\history")
'↑の場合、「履歴」をHTML化します。ただし、履歴をため込んでいる場合(999日など)は、
'死ぬほど時間がかかります。
'10000件のURLだと1時間くらいかかる…かも。
Set objFolder=Win.NameSpace(ssfFAVORITES)

msgbox "ただいまから、お気に入りをHTML化します。"

Set ts=Fs.CreateTextFile(strPath,True)

ts.WriteLine "<html><head><title>お気に入りリスト</title></head><body>"

Call RecSrch(objFolder)

ts.WriteLine "</body></html>"
ts.Close
msgbox "終了。"

Sub RecSrch(obj)
: ts.WriteLine "<blockquote>"
: For Each objItem In obj.Items
: : If objItem.IsFolder Then
: : : Set objSubFolder=objItem.GetFolder
: : : ts.WriteLine "<p>" & objSubFolder.Title & "<br>"
: : : For Each objSubItem In objSubFolder.Items
: : : : If objSubItem.IsFolder=False Then
: : : : : str=objSubFolder.GetDetailsOf(objSubItem,-1)
: : : : : If InStr(str,vbCrLf) Then
: : : : : : arr=Split(str,vbCrLf)
: : : : : : ts.WriteLine "<a href=""" & arr(1) & """>" & arr(0) & "</a><br>"
: : : : : ElseIf str<>"" Then
: : : : : : ts.WriteLine "<a href=""" & str & """>" & str & "</a><br>"
: : : : : End If
: : : : End If
: : : Next
: : : ts.WriteLine "</p>"
: : : Call RecSrch(objSubFolder)
: : End If
: Next
: ts.WriteLine "</blockquote>"
End Sub

たね さん 2004年 06月 24日 15時 14分 38秒

はじめて投稿します。たねです。

ASPよりVBSファイルを実行したいのですが、うまくいきません。

リロードしようとしたままの状態で、最終的にはIISにも接続できなく
なります。こうなると、サービス(World Wide Web Publishing)を停止
することができず、Windows タスク マネージャーにてIWAM_xxxxxが実
施しているdllhost.exeを強制終了させて始めて、サービスが停止でき
る状況です。

問題となっているソースです。

[test.asp]
<%
on error Resume Next
Set WshShell = CreateObject ("WScript.Shell")
WshShell.Run "C:\Inetpub\wwwroot\test.vbs"   'ここで処理が止まっている模様、コメントにすると動作
Set WshShell = Nothing
%>

[test.vbs]
Dim fso, MyFile
Set fso = CreateObject("Scripting.FileSystemObject")
Set MyFile = fso.CreateTextFile("C:\Inetpub\wwwroot\test.txt", True)
MyFile.WriteLine("This is a test.")
MyFile.Close
wscript.quit 0

C:\Inetpub\wwwroot\test.aspからC:\Inetpub\wwwroot\test.vbsを呼び
出すだけのなんとも簡単なソースなのですが。

[テスト環境]
WindowsXP Professional
IIS Ver5.1 ※インターネット インフォメーション サービス画面より
Windows Script Host Version 5.6

以前、WindowNT4.0&IIS4.0の時は問題なく実施できたのですが・・・

IIS5.0からは、IUSRとIWAMにプロセスが分離されたと聞きますが、
ここが問題なのでしょうか。(権限とか?)

この掲示板を隅から隅まで熟読すれば、乗っているのかも知れませんが、
どなたか、わかる方がいらっしゃればご教授願います。

いりや さん 2004年 06月 24日 13時 36分 41秒

vagabond さんへの初回回答は、
http://www.roy.hi-ho.ne.jp/mutaguchi/bbs/list108.shtml
こちらのてっぺんに記録されていますね。新しいページに切り替わった
関係で。

いりや さん 2004年 06月 24日 02時 35分 58秒

ちょいと遅くなりました。

ばんのしゃーによかばんた さん 2004年 06月 09日 14時 19分 56秒
| しかし、DeleteFileのほうは、
| >いりや さん 2004年 06月 06日 20時 39分 19秒
| >観測したのは Scripting.FileSystemObject>>deleteFile() メソッドを実行した
| >後にスクリプトホスト (wscript.exe) が実行を終えようとした時にスクリプト
| >ホストがエラーを報告し実行を中断する、という事象でした。
| ということなので、これをまさか「仕様」と言わないでしょうから、
| DeleteFileを使うひとがみんな考慮しないといけない、ということにはならないだろう、
| ということです。

なるほど、おっしゃる意味は分かりました。再現が終わったらまたこの話は続き
をさせてください。

それから DDE の話は、実はあれから msdn のユーザーインタイフェイスのガイ
ドラインを読んで Windows Shell の責任範囲 (Shell はどんなサービスの提供
に責任があるのか、あるいはないのか) を知り、DDE の枠組みの位置づけについ
てオーバースペックなところを勝手に考えていたところがありそうだ、というこ
とが分かりました。

せっかくなのでこちらも上記の話が整理ついたところでそのあたりの話と、では
そういう前提で invokeVerb() メソッドの実装仕様は満足いけるものかという自
分の思いを、まとめたいとおもいます。

いりや さん 2004年 06月 24日 02時 27分 25秒

vagabond さんのスクリプトの面白い所は Dynamic HTML Object Model をユーザ
・インターフェイス・ビルダとして使っているところで、前々から興味をもって
いました。

今回、触発されて、vagabond さんのスクリプトを JScript にポーティングして
みました。WSH/JScript で同様のことを考えていらっしゃる方のご参考になれば
幸いです。

ちなみに書いていて、今後の課題だな〜と思ったのは、InternetExplorer.Application
オブジェクトを複数つかって複数のウインドウを表示するときに、それらを最終
的に解放するタイミングを制御することでしょうか。いまは onQuit 広域変数を
解放タイミングを伝えるフラグに利用しているのですがこれだと一枚のウインド
ウしか対応しません。

またウインドウを構成する要素をハードコーディングしているので、パラメータ
として外だしできる枠組みも欲しいところです。ま、このあたりの枠組みは、ど
のインターフェイス・ビルダも用意しているのでそれを参考にできればとはかん
がえています。

var onQuit = false;
var d = new Dialog();

mainLoop(d);

function mainLoop (d) {
    while (true) {
        WScript.sleep(0.1 * 1000);
        if (onQuit) {
            // onQuit が d および d に付随する資源を解放する引き金とする。
            // d は InternetExplorer.Application オブジェクトなので quit()
            // メソッドを明示して呼ばないと対象ウインドウ (外部資源) を解放
            // しない。そのため、wscript.exe 処理系の実行を終了する前に、
            // quit() メソッドを呼び、資源の解放を依頼する。
            d.quit();
            WScript.quit();
        }
    }
}

function Dialog_OnQuit() {
    onQuit = true;
}

function Dialog () {
    var e = WScript.createObject('InternetExplorer.Application', 'Dialog_');
    var wait = function () {
        while (e.busy || e.readyState != 4)
            WScript.sleep(0.1 * 1000);
    }
    var navigate = function () {
        if (arguments.length == 0) {
            e.navigate('about:blank');
            wait();
        }
        if (arguments.length == 1 && typeof(arguments[0]) == 'string') {
            e.navigate(arguments[0]);
            wait();
        }
    }
    var initialize = function () {
        navigate();
        e.document.write(new Array(
            '<html>',
            '<head></head>',
            '<body>',
            '<table>',
                '<tr><td>ユーザー名</td>',
                    '<td><input type=textbox name=UserID></td></tr>',
                '<tr><td>パスワード</td>',
                    '<td><input type=password name=Password></td></tr>',
            '</table>',
            '<br><br>',
            '<input type=button value=" OK " class=ok id=cmdOK>',
            '<input type=button value="CANCEL" class=cancel id=cmdCancel>',
            '</body>',
            '</html>').join(''));
        e.document.close();
        wait();

        var w = e.document.parentWindow;
        w.moveTo(w.screen.availWidth / 2 - 150, w.screen.availHeight / 2 - 150);
        w.resizeTo(300, 200);
        w.document.title = 'ネットワークドライブマップ';

        e.toolbar = false;
        e.statusbar = false;
        e.menubar = false;
        e.resizable = false;
        e.visible = true;
    }
    var onClickHandler_cmdOK = function () {
        var mbUID = new String(e.document.parentWindow.document.all.UserID.value);
        var mbPASS = new String(e.document.parentWindow.document.all.Password.value);
        var WshShell = new ActiveXObject('WScript.Shell');
        WScript.echo('You clicked OK. Value: ' + mbUID + ' ' + mbPASS);
        onQuit = true;
        return;
        // 以下は未テストのため、上記 return で関数を脱出している!
        // WshShell.Run "net use * /delete /y",0,1
        // Wscript.Sleep 1000
        // WshShell.Run "net use k: \\サーバー名\共有名 /user:ドメイン名\"&mbuID&" "&mbPASS&" /persistent:no",0,1
        // Wscript.Sleep 2000
        // WshShell.Run "explorer /e, K:\"
        WshShell.run('net use * /delete /y', 0, 1);
        WScript.sleep(1000);
        WshShell.run('net use k: \\\\サーバー名\\共有名 /user:ドメイン名\\' + mbUID + ' ' + mbPASS + ' /persistent:no', 0, 1);
        WScript.sleep(2000);
        WshShell.run('explorer /e, k:\\');
        onQuit = true;
    }
    var onClickHandler_cmdCancel = function () {
        WScript.echo('You clicked Cancel.');
        onQuit = true;
    }
    var registerHandlers = function () {
        var w = e.document.parentWindow;
        w.document.all.cmdCancel.onclick = onClickHandler_cmdCancel;
        w.document.all.cmdOK.onclick = onClickHandler_cmdOK;
    }
    initialize();
    registerHandlers();
    return e;
}

Return