VbScriptの罠①「HTAでのDoEvents」


先日から、がりがりと
HTA上で、VbScriptをいじってるけど、VBや、OfficeのVBAと同じ感覚で
やってると以外とはまること多い。

関数のformatやらstrconvrがなかったり
その手のこまごましたものも多々あるんだけど
一番困ったことは、なんといいても

DoEvntsがないことでしょう。

なんかしら、代わりのものがあるやろと
sleepっぽいのやら、waitっぽいのやら
さがしてみるもない!
(vbScriptだけの話しなら、sleepはあるけどHTA上では使えない)

結論的にHTA上のVBScriptでは、
Windowsに制御を戻す処理がないことが確定!

これは、困った。

今作ってるのは、HTAで大量のデータ処理をやってるんだけど
当然ごとく大量にループするわけで
その間、がっつり固まった感じになってしまう。
先日かいたように
データ処理が完了したら使わなくなる代物なので
そんなにちゃんとしたものでなくていいのだけど
一応、残時間把握したいし、進捗状況とかもろもろ
画面に表示したい。


さらに恐ろしいことに、
HTAは、固まる時間が長引くと
「この画面が重くなってるけどとめますか?はい、いいえ」
みたいな画面がでてきて
(よく、ブラウザーで重いページをみると出てくる奴)
処理をとめてしまうのです!

回避すべき方法をいろいろ探すと、
おおむねsetInterval()を使えと書いてある。

うーむ、setIntervalを使う方法は意味はわかるんだけど
すでに作ってしまったloopロジック、この方法に乗せかえるの、ちょっと面倒な感じ。
呼び出す関数に引数があると
さらにじゃーくさい感じ。


で、考えました。

幸い、私自身の環境は各種開発ソフトがそろっているので
VB.netで
DoEventsして、終了だけするexeを作成。


Sub DoEvents
  Dim objShell
  Set objShell = CreateObject("Wscript.Shell")
  objShell.Run "DoEvents.exe" 
End Sub


こんな感じのを、ループにはさむと
ちゃんと描画された!

少々反則的で、
exeを毎ループ実行するというのは 当然余分にリソース食うのは明白なので
ちゃんとした解決ではないんだけど

 一応は、なんとかりそうな感じ。

最終的には、毎ループごとに、描画するほどでもないので
パラメータの回数ごとに、DoEventsを実行するように


Sub CallDoEvents(inParam)
  If lngCount Mod inParam  = 0 Then
    Call DoEvents()
  End If             
End sub

こんな感じにして、

 各PGやループの量や、処理速度に応じて
いい感じに調節して今回は逃げ切ります。

誰かええ方法知ってたら教えてください!
 

4 件のコメント :

  1. はじめまして。

    どうも、HTAではWscript.ShellオブジェクトのRunメソッドを呼び出すだけでDoEvents的な事が行われるみたいです。
    ご存知のようにHTAではSleep関数が使えないので、以下のようなSleep.vbsを作成してそれをRunメソッドで同期実行することで代用していたのですが、その過程で上記の事に気づきました。

     On Error Resume Next
     WScript.Sleep WScript.Arguments.Item(0)

    もちろん自作exeを起動する方法でも全然構わないと思います。 Wscript.exeより軽量なexeであれば、なおさらに。
    ただVB.netで作ったexeだと.Net Frameworkのインストールが必要なのが環境によってはネックになってしまいますね。

    最後に、ソースの簡略化の為にそう記載しているだけかとも思いましたが、気づいた事を一つ。
    ループ中でオブジェクト生成を繰り返すのも、少なからずリソース負担がありますので、objShellの宣言およびCreateObject("Wscript.Shell")は、あらかじめやっとくのがいいかと思います。

    根本的な解決策でもなんでもなく、単なるツッコミに終始したようで大変失礼しました。

    返信削除
    返信
    1. 初めまして。
      そしてコメントありがとうございます!

      いやはやなんというか、
      こんな駄文blogちゃんと読んでくれてる人がいるなんて嬉し限りですねー。
      (shumさんのコメントがこのblog初コメントなんです!)

      おっしゃる通りで、
      .netのexeだとスピードと.Net Frameworkの環境面が気になってたので
      この後いろいろあいまで実験するさなか、vbsファイルに記述したsleepでいけることに気づき、最終的にはそれで本番をのりきりました。
      (なぜこちらを先に気づかなかったのか自分でも不思議です。たぶんテンパってたんでしょう)
      ちゃんと追記しとくべきでしたねー。

      objShellについても、おっしゃる通りで
      他のメソッドでも使用してますので
      実ソースでは、頭で宣言、生成しちゃってます。
      こちらも、説明なくすいません。

      とにかく、貴重なコメントありがとうございました。
      こんなにちゃんとした返信いただけると、書いた甲斐があったなーという感じです。

      削除
  2. こんにちは。

    >実ソースでは、頭で宣言、生成しちゃってます。

    あちゃー。 やっぱそうでしたか。
    偉そうなこと書いてスミマセンでした(>_<)

    せっかくの初コメだったのにトンチンカンな事書いてしまって恐縮です。

    私も最近ちょっとしたフリーソフトを公開するためのサイトを開設して思ったのは、コメント書いてくれる人なんて、アクセス数・ダウンロード数から見るとほんの一握りです。
    昨今は検索エンジンがスゴく発達してるので、何かの拍子でたどり着いて、コメント書いてくれないまでも読んでくれている人はたくさんいると思います。
    ちなみにgoogleがまだ存在していない時代ではだいたい同じようなサイト内容でも、アクセス数なんてほとんど皆無でした(^_^;)

    話は変わりますが、私には絵ゴコロやデザインセンスとかがからっきしなので、CGとか作れる人って凄いなーって思います。
    【蒼姫ラピス】Silent Worldも拝見させていただきました。音楽とマッチしててとてもステキですねo(^▽^)o

    返信削除
    返信
    1. いえいえ、こちらが適当に書いちゃってるのが悪いので
      ご指摘いたたけてありがたいかぎです。
      読む人目線で、意見くださると
      今後気をつけようと思えますので。

      映像まで見ていただいたんですね。ありがとうございます。
      僕も絵心もなく、デザインセンスもない人間ですよー。
      cgは最近始めたもので、30過ぎてから老化した頭に鞭うってがんばりました。
      結構プログラムで補う部分があるので、プログラムを知ってるといろいろ有利ですよ。shumさんも、もし興味あるならオススメです。

      削除