お世話になっております。
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件)

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


外さないでください

>後、自分でも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

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

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で質問しましょう!

このQ&Aと関連する良く見られている質問

Q解凍ソフト LhacaとLhasaの違い

タイトルのように解凍ソフト LhacaとLhasaの違いを教えてください。お願いします。

Aベストアンサー

Lhacaは圧縮、解凍ソフトで、

Lhasaは解凍のみなのでは?

あとは作者が違いますね(^^ゞ

QIf myCityBUNRUINO = 2 Then Cells(myPrefNO + 3 - 47 - myCityNu, 24) = myTantou こちらについて教えていただきたいです。

myTorikomibi = Range("A2").Value
If myCityBUNRUINO = 0 Then Cells(myPrefNO + 3, 4) = myTantou
If myCityBUNRUINO = 1 Then Cells(myPrefNO + 3 - 47, 14) = myTantou
If myCityBUNRUINO = 2 Then Cells(myPrefNO + 3 - 47 - myCityNu, 24) = myTantou
For i = 1 To 3
If myCityBUNRUINO = 0 Then Cells(myPrefNO + 3, i + 4) = myTorikomibi
If myCityBUNRUINO = 1 Then Cells(myPrefNO + 3 - 47, i + 14) = myTorikomibi
If myCityBUNRUINO = 2 Then Cells(myPrefNO + 3 - 47 - myCityNu, i + 24) = myTorikomibi
Next i
マクロを編集しようとしましたところこちらが解読できづに困っています。
こちらだけとりだして実行しながら解読していますが混乱してしまっています。ご存知の方いらっしゃいましたら教えてください。Then以降がわかりません。よろしくお願いいたします。

myTorikomibi = Range("A2").Value
If myCityBUNRUINO = 0 Then Cells(myPrefNO + 3, 4) = myTantou
If myCityBUNRUINO = 1 Then Cells(myPrefNO + 3 - 47, 14) = myTantou
If myCityBUNRUINO = 2 Then Cells(myPrefNO + 3 - 47 - myCityNu, 24) = myTantou
For i = 1 To 3
If myCityBUNRUINO = 0 Then Cells(myPrefNO + 3, i + 4) = myTorikomibi
If myCityBUNRUINO = 1 Then Cells(myPrefNO + 3 - 47, i + 14) = myTorikomibi
If myCityBUNRUINO = 2 Then Cells...続きを読む

Aベストアンサー

こんにちは。maruru01です。

ヘルプはご覧になりましたか?
特に、Cellsについて。
Cellsは、

Cells(行番号, 列番号)

で、セルを参照します。
なので、各条件の時に、変数「myTantou」や「myTorikomibi」に格納されている値をそれらのセルに代入しているだけですが。
ただし、行番号が、

「myPrefNO + 3 - 47」
「myPrefNO + 3 - 47 - myCityNu」

などとちょっとややこしくなっていますが。
これも、変数「myPrefNO」「myCityNu」に入っている値から行番号が決まるというだけです。
例えば、
myPrefNO=60
myCityNu=2
なら、下の例は、
60+3-47-2=14
で、14行目となるということです。

Q圧縮・解凍ソフト Lhacaについて。

今、圧縮・解凍ソフトのLhacaをダウンロードしたのですが、使用方法がよく分かりません。
そこで、Web検索をしてみたのですが圧縮の仕方解凍の仕方のみしか載っていなく、ある映像などを圧縮した際それを、Web上に載っけたりする方法がわかりません。
特に、ご存知の方でいいのですが、Yahooオークションなどオークションに出展する際の写真を圧縮してそれを搭載したいのですが、もし知っている方がいたらその方法も教えてください。
よろしくお願いいたします。

Aベストアンサー

おっしゃりたいことは大きな画像のサムネイルを作りたいと言う事だと理解しました。
サムネイルを作る場合は下記のような画像変換ソフトなどを使います。
Lhacaは大きなファイルをディスク上で場所をとらないようにしたり、フロッピーディスクでデータを受け渡すために
ファイルを小さく圧縮するソフトですので用途がまったく違います。

参考URL:http://www.vector.co.jp/vpack/browse/pickup/pw4/pw004737.html

QMicroSoft BasicのDim文とVisualBasicのDim文の違い

私が20年前にMicroSoft Basicを使っていたときは、DIM文はDIMENSIONの略で配列型変数の宣言に使っていました。

最近VisualBasicの勉強を始めたのですが、変数の宣言はすべてDim文になっており、昔のMS BasicのDim文と意味合いが変わっているのに驚いています。

ここで質問させてください。
・なぜ配列を意味するDimension文が変数の宣言なのか?
・どのバージョンのBasicからDim文の意味が変わったのか?

私が使用していたのはNEC N-Basic,N-88Basic,N-98Basicです。

Aベストアンサー

VISUAL BASIC のDimは ディメンジョンの略です。
私の経験ではVB2.0時代からありました。

配列0を考えた場合変数とおなじであるからだとおもいます

Q解凍ソフト

解凍ソフトをまちがって削除してしまったんでですが、
以前と同じのがみつからずこまっています。
一応代わりの解凍ソフトはみつかりましたが、
以前のやつはダイルをダブルクリックするだけで解凍できたんですが、
今つかっている+Lhacaというのは、いちいち+Lhacaのアイコンまで
ファイルをドラッグしてもっていかなければならないのでめんどうです・・
クリックするだけで解凍してくれる解凍ソフトがあったら教えてください。確か以前のは解凍したときに上と下にどれだけすすんでいるかわかるやつがありました・・

Aベストアンサー

一番使いやすい解凍ソフトがあります。有名ですけど。
「Lhaplus」ラプラスというソフトです。
こちらなら、何でも解凍できますので、良いとお思います。
ダウンロードURLは
http://search.vector.co.jp/search?query=%89%F0%93%80
こちらは、有名なフリーソフトのサイトです。

Q条件付きコンパイル: #IF 1 Then と #IF 0 Then

条件付コンパイルで、
『#If 1 Then』と『#If 0 Then』の条件の違いを教えてください。


『#If ○○○=1 Then』などの場合はわかるのですが、
単に『#If 1 Then』の場合は何をもって真となるのでしょうか?

よろしくお願いいたします。

Aベストアンサー

条件式は、強制的に「True」又は「False」に解釈されます。

で、「数値」を「True」又は「False」に解釈する場合、
「0」は「False」、「0以外」は「True」になります。
(http://msdn.microsoft.com/library/ja/default.asp?url=/library/ja/script56/html/vsfctcbool.asp)

つまり、
『#If 1 Then』は、「必ずTrue」=常に有効
『#If 0 Then』は、「必ずFalse」=常に無効
に成ります。

Q+Lhacaのダブルクリック解凍ができない

解凍ソフトに+Lhaca1.24を使用しています。

自宅のパソコンにインストールし、
圧縮ファイルを解凍しようとし、
圧縮ファイルをダブルクリックしたところ、
圧縮ファイルの中身が表示されるだけで、
解凍がされません。
(WinXPの標準圧縮ファイルを展開するイメージ)

関連付けは完璧に完了しています。
Lhacaの再インストールも行いましたが、
結果は変わりませんでした。

どなたか教えていただけますでしょうか。
よろしくお願い致します。

Aベストアンサー

>(WinXPの標準圧縮ファイルを展開するイメージ)

・・・ということですので、解凍はされているはずです。
XPでZIPファイルをダブルクリックした時のように通常の
フォルダ画面が開く場合は、その画面のアドレス欄を見て
解凍されたファイルの場所を確認してください。
※アドラス欄が表示されていない場合は、「表示」→
「ツールバー」→「アドレスバー」で表示されます。
※+Lhacaの設定画面からも解凍先の確認は出来ます。
(「解凍のたびに指定」を選択してある場合は、解凍時
に自分で指定した場所を開いて確認してください。)

QDim x As Integer = 0

いつもお世話になっております。

只今、本に記載してあるソースコードを手入力しています。
標記のように入力したら、『コンパイルエラー 修正候補:ステートメントの最後』というエラーが出ました。

(1)このエラーは無視してもよいのでしょうか?
(2)そもそも、変数の宣言文の後ろに=0をつけている意味がわかりません。当方VB初心者です。

よろしくお願いいたします。

Aベストアンサー

この点は(変数の宣言と初期化は)言語による、と考えるべきです。
この質問は何の質問か。
VB系統らしいことは判るが
VB以外のBASIC
VB6
VBA
VB.NET系統
のどれか質問に書くべき。質問者は経験が無くて、視野がそこまで行かないのかも知れないが。
ーーー
VBAでは(多分VBでも同じ。テスト環境がないので)
Sub test01()
Dim x As Integer
x = 0
MsgBox x
End Sub
はOK
ーー
Sub test01()
Dim x As Integer =0
MsgBox x
はDim x As Integer =0
と入力した段階でエラー。
http://www.bunsugi.ed.jp/vba4graduate/vba_hensuusyokika.htm
ーーー
定数のConstであればこういう書き方はOK
Sub test01()
Const x As Integer = 0
MsgBox x
End Sub
ーーー
VB.NETでは、OK
Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
Dim x As Integer = 10
MsgBox(x)
End Sub
ーー
Javaでは可能であるようです
http://msugai.fc2web.com/java/var2.html
ーーーーー
>ろに=0をつけている意味がわかりません
宣言と同時に値を与える=初期化する

この点は(変数の宣言と初期化は)言語による、と考えるべきです。
この質問は何の質問か。
VB系統らしいことは判るが
VB以外のBASIC
VB6
VBA
VB.NET系統
のどれか質問に書くべき。質問者は経験が無くて、視野がそこまで行かないのかも知れないが。
ーーー
VBAでは(多分VBでも同じ。テスト環境がないので)
Sub test01()
Dim x As Integer
x = 0
MsgBox x
End Sub
はOK
ーー
Sub test01()
Dim x As Integer =0
MsgBox x
はDim x As Integer =0
と入力した段階でエラー。
http://www.bunsug...続きを読む

Q自動解凍機能がある圧縮ソフト

圧縮・解凍ソフトとして、いつもLhacaを便利に活用しているのですが、自動解凍機能がなく、先方が解凍に苦労することがあります。
自動解凍機能があるフリーの圧縮ソフトがあれば、ご紹介いただきたいのですが、どなたかご存知の方、いらっしゃいますか?

Aベストアンサー

LhacaやLhasaは過去のソフトで、軽くてよいのではありますが、対応形式に乏しく、また過去のソフトであることから多くのバグが放置されたままです。また、デラックス版などでRAR形式に対応とうたっておりますが、現在のRARにはまったく対応してないといった現状です。

自己解凍形式を作成でき、初心者の方にもお薦めであり、対応形式も豊富で便利なものといえばLhaplusがお薦めです。
http://www.vector.co.jp/soft/win95/util/se169348.html

是非どうぞ。インストールするは、Lhacaをアンインストールしてからどうぞ。

Q'2465'指定した式で参照している'直線Aii'フィールドが見つかり

'2465'指定した式で参照している'直線Aii'フィールドが見つかりません。

入力されたテキストDELTUKIをiiにセットして直線Aii~Ciiに反映させたいです。
DELTUKIには0~12までのどれかがセットされて、00の場合には未可視、それ以外は
該当月の直線Aii~Ciiを可視化させたいです。
ですが、上記エラーが発生します。
どなたかご指南頂きたくよろしくお願い致します。
※.メイン画面の画像添付参照願います。
※.vba vb6 winXP
SetLowerLine:
With objrep
!直線103.Visible = True
!直線104.Visible = True
!直線105.Visible = True
!直線106.Visible = True
!直線107.Visible = True
End With
'Reports(stdocname)!直線103.Visible = True
'Reports(stdocname)!直線104.Visible = True
'Reports(stdocname)!直線105.Visible = True
'Reports(stdocname)!直線106.Visible = True
'Reports(stdocname)!直線107.Visible = True

Format ("00")
ii = Forms!メイン画面![テキストDELTUKI]
If ii = "00" Then
Else
objrep.Controls("直線A" & "ii").Visible = True
objrep.Controls("直線B" & "ii").Visible = True
objrep.Controls("直線C" & "ii").Visible = True
End If

'2465'指定した式で参照している'直線Aii'フィールドが見つかりません。

入力されたテキストDELTUKIをiiにセットして直線Aii~Ciiに反映させたいです。
DELTUKIには0~12までのどれかがセットされて、00の場合には未可視、それ以外は
該当月の直線Aii~Ciiを可視化させたいです。
ですが、上記エラーが発生します。
どなたかご指南頂きたくよろしくお願い致します。
※.メイン画面の画像添付参照願います。
※.vba vb6 winXP
SetLowerLine:
With objrep
!直線103.Visible = True
!直線104....続きを読む

Aベストアンサー

すみません、先日のこちらのご質問での回答者です:
http://oshiete1.goo.ne.jp/qa5770608.html

前回の回答2への補足の件のうち、「(2)」と「(3)」については
結局私では対処法の見当をつけかねたままなのですが(汗)、
本件についてだけはどうにかなりそうなので、回答をつけさせて
戴きます。

・・・というか、前回「"」を外すことを指摘した際に気づいて
いればよかったのですが、これも見落としていました(汗)
以下の部分を、下記のように修正してください。

【現在】
Format ("00")
ii = Forms!メイン画面![テキストDELTUKI]

If ii = "00" Then
Else
  objrep.Controls("直線A" & "ii").Visible = True
  objrep.Controls("直線B" & "ii").Visible = True
  objrep.Controls("直線C" & "ii").Visible = True
End If

【修正】
'変数「ii」に対して、Format関数で桁表示を指定
ii = Format(Forms!メイン画面![テキストDELTUKI], "00")

If ii = "00" Then
Else
  '「ii」を変数として使用するため、「"」は外します
  objrep.Controls("直線A" & ii).Visible = True
  objrep.Controls("直線B" & ii).Visible = True
  objrep.Controls("直線C" & ii).Visible = True
End If


・・・以上です。

これで、「テキストDELTUKI」に1桁の数字(「1」や「2」など)を
指定した場合も、「直線A01」や「直線A02」に処理が行われる
ようになると思います。

すみません、先日のこちらのご質問での回答者です:
http://oshiete1.goo.ne.jp/qa5770608.html

前回の回答2への補足の件のうち、「(2)」と「(3)」については
結局私では対処法の見当をつけかねたままなのですが(汗)、
本件についてだけはどうにかなりそうなので、回答をつけさせて
戴きます。

・・・というか、前回「"」を外すことを指摘した際に気づいて
いればよかったのですが、これも見落としていました(汗)
以下の部分を、下記のように修正してください。

【現在】
Format ("00")
ii = For...続きを読む


人気Q&Aランキング