アプリ版:「スタンプのみでお礼する」機能のリリースについて

お世話になっております。
VBScriptを使用して、あるディレクトリにあるCABファイルを展開するプログラムを作成しているのですが問題がありまして、分かる方いらっしゃいましたらぜひご教授頂きたいです。

■問題
CABファイルを展開している間はスクリプトをストップさせ、展開が終了したら次のCABファイルを展開しにいくと言うプログラムですが、CABファイル展開が終了しても、sleepのDo whileを抜けてくれない。

■以下ソースです↓↓↓
Option Explicit
On Error Resume Next

Dim objWshShell ' WshShell オブジェクト
Dim strHomePath ' ホームパス
Dim objFSO ' FileSystemObject
Dim strFolder ' フォルダ名
Dim strCab ' CABファイルパス
Dim CmdLine ' 実行コマンド
Dim objExecCmd ' 実行コマンド情報

strFolder = ""
strHomePath = ""
strCab = ""

レジストリからフォルダパスを取得する処理

If strHomePath <> "" Then
Set objFSO = CreateObject("Scripting.FileSystemObject")

If Err.Number = 0 Then

strFolder = strHomePath
' CABファイルのパス
strCab = strFolder & "\CabG.CAB"
' CABファイルの展開コマンド作成
CmdLine = "expand """ & strCab & """ -f:* """ & strFolder & """"

'CABファイルの存在確認
If objFSO.FileExists(strCab) = True Then

' CABファイル展開
objWshShell.Exec(CmdLine)

' 実行コマンド格納
Set objExecCmd = objWshShell.Exec(CmdLine)
WScript.Echo "成功:コマンドを格納" & CmdLine & Err.Description

' 実行コマンドが終了するまで待つ
Do While objExecCmd.Status = 0
WScript.Sleep(3000)
              WScript.Echo "展開中です" & Err.Description
Loop

WScript.Echo "成功:コマンド終了" & CmdLine & Err.Description

'展開したCABファイルを削除する
'objFSO.DeleteFile strCab, True

'展開で作成されるOSDファイルを削除する

Else
WScript.Echo "エラー:" & strCab & "が存在しません" & Err.Description

End If

順次同じようなロジックで次のCABファイルを展開する

■↑↑↑↑

DOS画面から起動すると、do while文が永遠に抜けれなくなります。。。
いろいろと調べて試行錯誤しているのですが、なかなか解決に至りません。
ぜひ、よろしくお願い致します。

A 回答 (3件)

stdin,stdout,stderrのバッファは有限です。


サイズは256byteか1024byte位だったと思います

そもそも、コンピュータ中で無限はありません。

無限に見えるバッファも、内部で保持しているバッファ以上のデータがきた場合は、バッファのサイズをリサイズしているだけです

例:Stringクラス、Listクラス

stdin,stdout,stderrはリサイズしません。
理由:通常大きなデータを扱わない。かつ、データの保持期間が短い。

今回のExecからexpand呼び出しでは、
通常CRTに出力したら勝手にクリアされるstdoutが、
どこにも出力されるところが無かった(stdoutがCRTに繋がっていない)ため、
stdout内が満杯になってしまったのが原因です。
なので今回は、stdoutをreadBuffにつなげてあげる事によって
stdout内が満杯にならないようにしてあげたわけです

expand以外にも、stdoutに大量出力するコマンドは注意する必要があります。
コマンドにsilentモードがあればいいですが。
    • good
    • 0
この回答へのお礼

なるほど、とても勉強になりました。
バッファと言う存在を、今まで全く気にしたことが無かったのがお恥ずかしい話です。。

ホントにありがとうございました。
これからも、もっとがんばろうと思います。

お礼日時:2007/04/26 18:38

>原因を探っているうちに、下記の場所が悪さしているみたいなのではずしました。


外さないでください

>後、自分でも2行いらないと思ったので、実行コマンド格納のSet objExecCmd = objWshShell.Exec(CmdLine)だけで実行すると、CABファイルの展開が不十分で終わるのです。。

検証してみた結果、expandの標準出力バッファが一杯になって、expandの処理が一時停止していました。
よって、whileの部分で標準出力バッファの中身を読み捨てればいいです。
補足:expand自体に、標準出力を抑制するスイッチがあれば、スイッチを付けるだけで解決したのですけどね。

○参考ソース
Option Explicit
On Error Resume Next

Dim objWshShell ' WshShell オブジェクト
Dim objFSO ' FileSystemObject
Dim strFolder ' フォルダ名
Dim strCab ' CABファイルパス
Dim CmdLine ' 実行コマンド
Dim objExecCmd ' 実行コマンド情報
dim readBuff

strFolder = "\temp\test"
strCab = "\temp\data2.cab"
' CABファイルの展開コマンド作成
CmdLine = "expand """ & strCab & """ -f:* """ & strFolder & """"

Set objWshShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")

'CABファイルの存在確認
If objFSO.FileExists(strCab) = True Then
' 実行コマンド格納
Set objExecCmd = objWshShell.Exec(CmdLine)
WScript.Echo "成功:コマンドを格納" & CmdLine & Err.Description
' 実行コマンドが終了するまで待つ
Do While objExecCmd.Status = 0' and objExecCmd.ExitCode = 0
readBuff= objExecCmd.StdOut.Read(5000) 'expandの標準出力を捨てる
'readBuff= objExecCmd.StdOut.ReadAll 'expandの標準出力を捨てる このメソッドでは、expandが終了しないと戻ってこない
WScript.Sleep(3000)
WScript.Echo "展開中です" & Err.Description
Loop

WScript.Echo "成功:コマンド終了" & CmdLine & Err.Description

'展開したCABファイルを削除する
''objFSO.DeleteFile strCab, True
Else
WScript.Echo "エラー:" & strCab & "が存在しません" & Err.Description
End If
    • good
    • 0
この回答へのお礼

marimari01さん、誠にありがとうございます。
これこそ意図していた動きです!!

いろいろ原因探っててobjExecCmd.Statusが永遠に0のままだと思っていたら、バッファがいっぱいになっていたのですね。
参考までにお伺いしたいのですが、なぜバッファがいっぱいになってるって分かったのでしょうか…?
(VBScript素人なもので、全く分かりませんでした。。)

ホントにありがとうございました。

お礼日時:2007/04/26 13:51

objWshShellの実体はどこでnewされているの?



>' CABファイル展開
>objWshShell.Exec(CmdLine)

>' 実行コマンド格納
>Set objExecCmd = objWshShell.Exec(CmdLine)
CABファイルの~
の2行いらないでしょ?
2重実行してないかい?

この回答への補足

marimari01さんの、おっしゃる通り二重実行されていましたので、
----------------------------------
' CABファイル展開
objWshShell.Exec(CmdLine)
-----------------------------------
の処理を消しました。
すると、CABファイルの展開が途中で止まります。

原因を探っているうちに、下記の場所が悪さしているみたいなのではずしました。
------------------------------------
' 実行コマンドが終了するまで待つ
Do While objExecCmd.Status = 0
WScript.Sleep(3000)
WScript.Echo "展開中です" & Err.Description
Loop
--------------------------------------
すると、スクリプトだけはどんどん進み終了しました。
(CABファイルの展開は追いつかず、スクリプトが終わった後も展開し続けています)

スクリプトの終了=CABファイルの展開終了 という形には言語の特性上等無理なのでしょうか・・・?

補足日時:2007/04/24 20:42
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
>objWshShellの実体はどこでnewされているの?
レジストリからフォルダパスを取得する処理のすぐ上で、Set objWshShell = CreateObject("WScript.Shell")を宣言しております(記載漏れ申し訳ないです。。)

後、自分でも2行いらないと思ったので、実行コマンド格納のSet objExecCmd = objWshShell.Exec(CmdLine)だけで実行すると、CABファイルの展開が不十分で終わるのです。。
(650ファイルのCABですが、33個展開して永久ループに陥ります)
※2行にすると全て展開してくれるのですが。。

説明分かりにくいかもしれませんが、上記の現象で何か思い当たる点などありますでしょうか?

お礼日時:2007/04/24 20:09

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!