プロが教える店舗&オフィスのセキュリティ対策術

環境
 VisualBasic2010Express
 WindowsXPSP3

前提
 あるプログラムをインストールしていると使えるコマンドがあります。
 コマンドプロンプト上から、バッチファイルを実行すると正常動作します。

 仮に j.bat とします。
 内容は
  dxf -o -s c:\test\test0.dxf
  dxf -o -s c:\test\test1.dxf
  dxf -o -s c:\test\test2.dxf
 こんな感じです。
 dxfの本体は、とあるフォルダにあるdxf.exeと思われます。
 (同名ファイルが複数あるので、特定できていません)
 パスが通っているのか、カレントディレクトリ(?)に関係なく実行可能です。
 このバッチファイルを実行すると処理は正常です。

現状
 VBでボタンを押したらバッチファイルと同じ処理をするプログラムを作りたいのですが
 実行する内容が毎回変化します。(dxfコマンドの引数が変わる) 
 よって同じバッチファイルは使えません。

 Dim Buffer(2) As String
 Dim Ret(2) As Integer

  for i =0 to 2
   Buffer(i) = "dxf -o -s c:\test\test" & i & ".dxf"
   Ret(i) = Shell(Buffer(i), vbNormalFocus)
  next i

 こんなプログラムですが、処理がされてません。
 コマンドプロンプトは一瞬3個開きます。
 dxfをフルパスで記述しても同じです。

質問(1)
   コマンドプロンプト上にメッセージが出ているようなのですが
   一瞬で消えるので読めません。
   コマンドプロンプトを閉じない方法はありませんか?
   なければ出力を残す方法はありますか?

質問(2)
   バッチファイルを毎回生成して、
   そのバッチファイルをShellコマンドで実行すれば動くのかも知れませんが
   他に良い方法はありませんか?

よろしくお願いします。
私は、VB2010は初めて。
VB6で2個プログラムを作った程度です。
コマンドプロンプト関連(?)は初めてです。

A 回答 (2件)

Buffer(i) = "dxf -o -s c:\test\test" & i & ".dxf"



のかわりに、

Buffer(i) = "dxf -o -s c:\test\test" & i & ".dxf & pause"

と書くと、最初のコマンドのあとにpauseが実行されるのでコマンドプロンプトが閉じないのではないかと思います。
    • good
    • 0
この回答へのお礼

ありがとうぎざいます。

質問(1)完全回答です。

お礼日時:2011/07/28 22:08

'検証環境は個人的な好みでMonoDevelopを使用。

まぁ変わらんだろ。
'俺も出たエラーをはっきり理解して解決しているわけではないのだが…
'用意したxyz.batの中身
'ping %1
'echo %1>>xxx.txt
'でPATHとか考えるの面倒だったので、一回コードをビルドして、exeのできたフォルダにbatを突っ込みました。

'俺のいるネットワークの環境は
'192.168.0.0/24である。よって以下のコードで、
'先のpingコマンドの終了を待たなければ、
'デフォルトゲートウェイである192.168.0.1へ打った、後の方のpingが先に終了し、echoが実行されるはず→実際そうなった。
'で、コメントアウトされている、p.WaitForExit()を有効にすると、先の方のpingが最初に終了した。

Option Explicit On
Option Strict On
Option Compare Binary
Option Infer Off

Public Class Application
Public Shared Sub Main()
'VB6由来のコードって厳密さに欠けるので好きじゃない。当然Shell関数も嫌いだ。
Dim psi As System.Diagnostics.ProcessStartInfo = New System.Diagnostics.ProcessStartInfo()

psi.FileName = "xyz.bat"

For Each s As String in new String(){"192.168.1.1","192.168.0.1"}

psi.Arguments = s

Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start(psi)
'p.WaitForExit()

Next

End Sub
End Class

===========================
さて、前に別なプログラムで実験したときに成功したのだが、
リファレンスに載っている通り、標準出力の内容は

ProcessStartInfoクラスのインスタンス(上記で言うpsi)の
RedirectStandardOutputプロパティをtrueにし、
かつ、UseShellExecuteをfalseにすることで、

取得したProcessクラスのStandardOutputプロパティからStreamReaderクラスのインスタンスが取得でき、ReadToEnd等で読み込めるはず。

サンプルコードがないのは、原因がある程度想像できているけど、検証するのが面倒くさい問題に当たったから
(MonoDevelopが先に出力を取っちゃうのでリダイレクト出来無いっぽい。が、それをファイルに出力しようとしたらそれはそれで怒られたしなあ)
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
ただし、私にとっては呪文だらけです。
呪文その1MonoDevelop。まず、.NET Frameworkから分からないが、調べる。
ネットワーク環境に対応させるため、OSに依存せずに(OS毎に勝手に変換する)使用でき
るプログラムの集合体だそうだ。
Java対抗?(Javaも良く分からないが無視)これを作ったマイクロソフトは、VBやVCに
使っている。
仕様が公開(標準化)されているため、マイクロソフト以外の第3者もこれを活用するソ
フトを作り得る。
使うといっても環境がないと使い辛いので、オープンソースで環境の実装プロジェクトが
いくつかありその一つがMono。
VBとの関係が分からないが、.NETだから一緒でしょ!と言っているらしい。
Pingの、存在はしっているが %1はなんでしょう。
引数に%なんてないが、辛抱強く調べると、間違っていた。
バッチファイルで使う引数か、25年位まえに使ったかもしれないが、まるで覚えてない。
Echo >>は、これでpingの結果がテキストに落ちるのだろう。
DOSで、コンベンショナルメモリを空ける時に使った気がする。
これで、回答6行分の意味が大まかに理解できた。
次にOptionはおまじないとして無視しよう。
Shell関数は、やめとけか、残念。
System.Diagnostics.ProcessStartは、外部アプリケーションを起動か。
メモ帳なら、System.Diagnostics.Process.Start("notepad.exe")
ここをまねすれば、できるのではということか?
p.WaitForExit()はコマンド終了まで待機で(100)とか入れれば1秒だけ待機。
なるほど、連続で同じことをやる場合のエラー回避に使うかもってことだ。(勝手読み)
===========================以下の記述は後からでもOKだろう。

まずは、やめとけと言われたが、中々回答がなかったので独自に調べたShell関数から。
コマンドプロンプトが開いていたので、まったく考えなかったが
>Buffer(i) = "dxf -o -s c:\test\test" & i & ".dxf"
この文字列に空白があると動かないことがあり、回避方法は
Buffer(i) = "cmd.exe /c dxf -o -s c:\test\test" & i & ".dxf"とcmd.exeを足すこ
と(開いているのに???)
ついでに引数を/c→/kにするとコマンドプロンプトが閉じない。これでデバック可能に
なった。
ここで、ご回答中の『PATHとか考えるの面倒だったので、一回コードをビルドして、』が
役にたった感謝します。
ところでshell関数の説明には、pathnameはフルパスでと書いてあることが多いが、
cmd.exeが動くってことは、結局パスが通っていれば、フルパスでなくても良いのではと
思う。
for-nextじゃまなので、省くとShell("cmd.exe /c dxf -o -s c:\test\test" & i &
".dxf", vbNormalFocus)で解決です。

次にご回答の猿まね
Dim psi As System.Diagnostics.ProcessStartInfo = New
System.Diagnostics.ProcessStartInfo()
psi.FileName = "cmd.exe"
psi.Arguments = " /c dxf -o -s c:\test\test" & i & ".dxf"
Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start(psi)
p.WaitForExit()
途中、「アプリケーションのコンポーネントで、ハンドルされていない例外が発生しまし
た」ってエラー(警告?)
で困ったが、こんな感じで動いている。

おまじないは要らなかった?(意味わかってませんが)
psi.RedirectStandardInput = False
psi.RedirectStandardOutput = True
psi.UseShellExecute = False
psi.CreateNoWindow = True

尚、ご回答中のOption○○○は
記述すると無効なステートメントと怒られます。

以上の結果、解決しましたので御礼申し上げます。

お礼日時:2011/07/28 22:06

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