DOBON.NET DOBON.NETプログラミング掲示板過去ログ

質問:VB.NETでのDOSコマンドを実行について

環境/言語:[VB.NET 2005 Framework2.0.50727]
分類:[.NET]

DOSコマンドを実行について質問です。

XCOPYを実行するプログラムを作成したく、
「DOSコマンドを実行し出力データを取得する」
「DOBON.NET > プログラミング道 > .NET Tips > プロセス」
を参考にDOSコマンドを実行するプログラムを作成しました。

しかし、実際にプログラムを起動してもXCOPYを実行しません。
(COPY,DIRは実行できました。XCOPYも直接DOS上で実行できたのでコマンド間違いはないといます。)

なぜ、実行できないのか解決方法などあればご教授お願い致します。

環境は下記の通りです。
Win2000 Pro SP4
VB.NET 2005 Framework2.0.50727

ソース
Dim results As String
Dim psi As New System.Diagnostics.ProcessStartInfo()

'ComSpecのパスを取得する
psi.FileName = System.Environment.GetEnvironmentVariable("ComSpec")
'出力を読み取れるようにする
psi.RedirectStandardInput = False
psi.RedirectStandardOutput = True
psi.UseShellExecute = False
'ウィンドウを表示しないようにする
psi.CreateNoWindow = True
'コマンドラインを指定("/c"は実行後閉じるために必要)
'psi.Arguments = "/c copy C:\copy1\*.txt C:\copy2"
psi.Arguments = "/c xcopy /d /Y /C /I C:\copy1\*.txt C:\copy2"
'起動
Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start(psi)
'出力を読み取る
results = p.StandardOutput.ReadToEnd
'出力された結果を表示
Console.WriteLine(results)
'WaitForExitはReadToEndの後である必要がある
'(親プロセス、子プロセスでブロック防止のため)
p.WaitForExit()
■No21623に返信(けんいちさんの記事)

> しかし、実際にプログラムを起動してもXCOPYを実行しません。
> (COPY,DIRは実行できました。XCOPYも直接DOS上で実行できたのでコマンド間違いはないといます。)

COPY や DIR は cmd.exe の内部コマンドですが、XCOPY は別途実行ファイルを実行する
外部コマンドになります。なので、XCOPY までのパスを指定してあげなければいけません。
直接DOS上…この場合コマンドライン上と言ったほうがいいかもしれませんが…で実行できた
のは、環境変数 path に XCOPY コマンドまでの検索パスが指定されているからです。

調べてみたところ、一般的には C:\WINDOWS\system32\xcopy.exe が XCOPY の実行ファイル
のようなので、XCOPY にあたる部分に C:\WINDOWS\system32\xcopy と設定してあげれば
大丈夫だと思います。

ただ、C:\WINDOWS\system32 は変更される場合もあるので、Environment.GetFolderPath など
を使って求めるべきでしょう。
http://dobon.net/vb/dotnet/file/getwindowsdirectory.html
2008/03/10(Mon) 14:27:20 編集(投稿者)

> しかし、実際にプログラムを起動してもXCOPYを実行しません。
> (COPY,DIRは実行できました。XCOPYも直接DOS上で実行できたのでコマンド間違いはないといます。)

特にエラーになるわけでもなく、ただ実行された形跡がないという状況でしょうか?
どのような出力がされましたか?


> 環境は下記の通りです。
> Win2000 Pro SP4
> VB.NET 2005 Framework2.0.50727

私の方で提示のコードをMainメソッドに記述しただけのプログラムを
コンパイルして実行しましたが、以下の環境では特に問題なく動作しました。

WindowsXP SP2 .NET Framework2.0と.NET Framework1.1

<修正>
XP2→SP2
</修正>
返信ありがとうございます。

ぽぴ王子さん
XCOPY.EXEが別になりました。
内部コマンド、外部コマンドとても参考になりました。
ただ、XCOPYを変更してもダメなようでした。
「psi.Arguments = "/c c:\winnt\system32\xcopy /d /Y /C /I C:\copy1\*.txt C:\copy2"」で確認
xcopy.exeが所定の場所に置いているのも確認しました。

よねKENさん
そうです、特にエラーが起きるわけでなく実行された形跡がありませんでした。
デバックで確認したところ「p.StandardOutput.ReadToEnd」は空白("")でした。
2008/03/10(Mon) 14:34:30 編集(投稿者)

> よねKENさん
> そうです、特にエラーが起きるわけでなく実行された形跡がありませんでした。
> デバックで確認したところ「p.StandardOutput.ReadToEnd」は空白("")でした。

結果が空白ですか。
ずばりこれが原因というのはちょっとわからないのですが、
一つ思い当たるのがあるので試してみてください。(うまく行ったらラッキー程度の案ですが)

psi.RedirectStandardInput = False
のところを
psi.RedirectStandardInput = True
にして実行してみるとどうでしょうか?

過去に以下のような事例がありましたので、
もしかしたら挙動に変化があるかもしれません。
http://dobon.net/cgi-bin/vbbbs/cbbs.cgi?mode=al2&namber=19163&no=0&KLOG=1
返信ありがとうございます。

ありがとうございます。
psi.RedirectStandardInput = Trueを実行したところ動作しました。

上記の対応でどうして、行くようになったのかは理解できていませんが
その点は勉強していこうとおもいます。

解決策は見つかったという事で解決済みにさせて頂きます。

よねKENさん、ぽぴ王子さんありがとうございました。


<実行確認後のソース>
Dim results As String
Dim psi As New System.Diagnostics.ProcessStartInfo()

'ComSpecのパスを取得する
psi.FileName = System.Environment.GetEnvironmentVariable("ComSpec")
'出力を読み取れるようにする
psi.RedirectStandardInput = True
psi.RedirectStandardOutput = True
psi.UseShellExecute = False
'ウィンドウを表示しないようにする
psi.CreateNoWindow = True
'コマンドラインを指定("/c"は実行後閉じるために必要)
psi.Arguments = "/c xcopy /d /Y /C /I C:\copy1\*.txt C:\copy2"
'起動
Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start(psi)
'出力を読み取る
results = p.StandardOutput.ReadToEnd
'出力された結果を表示
Console.WriteLine(results)
'WaitForExitはReadToEndの後である必要がある
'(親プロセス、子プロセスでブロック防止のため)
p.WaitForExit()
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板