C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[8]: コマンドプロンプトを実行する方法


(過去ログ 138 を表示中)

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■80927 / inTopicNo.1)  コマンドプロンプトを実行する方法
  
□投稿者/ ボロンゴ (1回)-(2016/08/21(Sun) 16:41:25)

分類:[.NET 全般] 


VB.NETでコマンドプロンプトを実行するには
以下の3種類の方法があります。


Call Shell("TaskKill.exe /f /IM i_view32.exe", vbHide, True) '0.047秒


Dim objWSH = CreateObject("WScript.Shell")
objWSH.Run("TaskKill.exe /f /IM i_view32.exe", vbNormalFocus, True) '0.071秒

Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start("TaskKill.exe /f /IM i_view32.exe") '0.069秒
p.WaitForExit()

Shellは昔からあるコマンドでProcess.StartはVB.NETでのみ使えるコマンドのようです。

これらの実行速度の比較を行ったのですが
0.047秒
0.071秒
0.069秒

でした。
もっとも簡単なShellコマンドがもっとも速いということが分かりました。

それでは、
objWSH.RunやProcess.Startの存在価値は何なのでしょうか?

どういう時に使い分ければ良いのでしょうか?




引用返信 編集キー/
■80933 / inTopicNo.2)  Re[1]: コマンドプロンプトを実行する方法
□投稿者/ 魔界の仮面弁士 (830回)-(2016/08/21(Sun) 23:15:03)
2016/08/21(Sun) 23:58:03 編集(投稿者)

No80927 (ボロンゴ さん) に返信
> VB.NETでコマンドプロンプトを実行するには
TaskKill.exe の呼び出しを コマンドプロンプトの実行と呼ぶのは語弊がありますが、それはさておき。


> 以下の3種類の方法があります。
他のアプリケーションを起動するためには、ほかにも WMI を使う方法、
具体的には Win32_Process クラスの Create メソッドで起動するという手もありますよ。

また、標準出力を受け取りたいのなら、WshScriptExec オブジェクトの
Exec メソッドを使うこともできるかと。VB.NET から使う機会はそうそう無いでしょうけど。

ほかにも ShellExecute(Ex) API を使う方法や、CreateProcess API を使う方法、
かわりどころでは BASP21 の Execute メソッドなど…。


> Dim objWSH = CreateObject("WScript.Shell")
CreateObject("WScript.Shell") で生成される「WshShell オブジェクト」は、
その名のとおり、WSH (1.0 以降) 向けに用意されたオブジェクトです。

WshShell の名のとおり、基本的には WSH 対応言語、特に VBScript や JScript 向けに
用意された機能ですが、同期呼び出しが行えることから VB5/VB6 や VBA からもよく利用されます。
なお、VB4 からの利用は推奨されていませんが、一応呼び出せます。
VB3 以下では利用できません。

WshShell は COM (ActiveX) のオブジェクトであるがゆえ、.NET から呼び出した場合には
使用後に Marshal.ReleaseComObject での解放処理が必要になることにご注意ください。
マーシャリング処理のボトルネックもありますし、特に理由がない限り、
.NET から利用することはお奨めしません。


> Call Shell("TaskKill.exe /f /IM i_view32.exe", vbHide, True) '0.047秒
Shell から返される戻り値は プロセスID です。(※)
上記では Call 呼び出しになっているため、戻り値を見ていませんけれどね。

※戻り値が プロセス ID となるのは、32/64bit の VB.NET および VB/VBA の場合です。
 16bit版 VB/VBA の Shell ではプログラムのインスタンス ハンドルを返していました。
 (VBA のドキュメントでは、戻り値は タスクID であると説明されています。
 Macintosh 版の Shell 関数を考慮して、そのように言い換えているのかな…)


> Shellは昔からあるコマンドで
VB2〜VB6 や VBA の Shell には第二引数までしかなく、常に非同期的に実行されていました。
同期モードやタイムアウト指定など、第四引数までが利用可能になったのは .NET になってからのことです。

ちなみに Shell 関数は VBScript では使えません。
また、.NET Compact Framework 上の VB.NET でも Shell 関数を利用できません。

蛇足ついでに言えば、Shell を VB.NET 以外の環境、たとえば C# から利用する場合、
もしくは VB.NET を vbruntime 無効オプション(/vbruntime- や /novbruntime など)で
呼び出している場合は、Microsoft.VisualBasic.dll への参照設定が必要となります。

最大の違いは、Shell で呼び出せるのは、実行可能ファイルのみに限られるという点です。
文書ファイルを指定して関連付け起動するような機能は無いため、
そのような用途が必要な場合は、WshShell.Run や Process.Start を使います。


> Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start("TaskKill.exe /f /IM i_view32.exe") '0.069秒
> p.WaitForExit()
Process.Start("TaskKill.exe /f /IM i_view32.exe") ではなく
Process.Start("TaskKill.exe", "/f /IM i_view32.exe") だと思いますよ。

Process クラスは、VB6 以下や VBA 、VBScript では使えない機能ですね。
挙げられた中ではもっとも高機能な方法なので、VB.NET からの呼び出しであれば、
ほとんどの場合、Process クラスさえあれば事が済みます。

ちなみに .NET Compact Framework では、上記の Process.Start(String) なオーバーロードは
用意されていません。Process.Start(String, String) や Process.Start(ProcessStartInfo)ならば
.NET Compact Framework であっても利用可能です。


> もっとも簡単なShellコマンドがもっとも速いということが分かりました。
キャッシュの効き方で時間が前後することもありそうですが、
この数十ミリ秒の実行速度差が問題になるような要件があるということでしょうか。


> どういう時に使い分ければ良いのでしょうか?
.NET Framework においては、基本的には Process クラスを使うのが正攻法でしょうね。

WshShell.Run は、VBScript (というか Windows Scripting Host) 向けですし、
Shell は 旧 VB との互換性維持のためのものと思っていただければ良いかと。
引用返信 編集キー/
■80937 / inTopicNo.3)  Re[2]: コマンドプロンプトを実行する方法
□投稿者/ ボロンゴ (4回)-(2016/08/22(Mon) 00:18:08)
詳細なご回答ありがとうございます。


process.startを使いたいと考えているのですが
ウインドウを非表示にして同期処理で実行したい場合、
以下のように複数行に渡って記述するしかないでしょうか?
Shellであれば一行でこれを書けるのですが
process.startだとこうするしかないでしょうか?

Dim psi As New ProcessStartInfo()
psi.FileName = "TaskKill.exe"
psi.WindowStyle = ProcessWindowStyle.Hidden
psi.Arguments = " /f /IM i_view32.exe")


Dim p As Process = Process.Start(psi)
p.WaitForExit()

引用返信 編集キー/
■80938 / inTopicNo.4)  Re[3]: コマンドプロンプトを実行する方法
□投稿者/ 魔界の仮面弁士 (831回)-(2016/08/22(Mon) 00:37:00)
2016/08/22(Mon) 00:37:39 編集(投稿者)

No80937 (ボロンゴ さん) に返信
> psi.FileName = "TaskKill.exe"
> psi.WindowStyle = ProcessWindowStyle.Hidden
> psi.Arguments = " /f /IM i_view32.exe")
起動させることが目的ではなく、i_view32.exe を終了させることが目的なのであれば、
Win32_Process クラスの Terminate メソッドも使えます。


> Shellであれば一行でこれを書けるのですが
Shell を使ってはいけない、というわけではないので、
要件に合うのであれば、Process を使わないのも選択肢の一つです。


> 以下のように複数行に渡って記述するしかないでしょうか?
纏めたければ、そのためのヘルパーメソッドを書くのも一つの手。


> Shellであれば一行でこれを書けるのですが
> process.startだとこうするしかないでしょうか?
あえて一行で書くとしたら。

Process.Start( New ProcessStartInfo("TaskKill", "/f /IM i_view32.exe") With {.WindowStyle = ProcessWindowStyle.Hidden} ).WaitForExit()
引用返信 編集キー/
■80939 / inTopicNo.5)  Re[4]: コマンドプロンプトを実行する方法
□投稿者/ ボロンゴ (7回)-(2016/08/22(Mon) 01:02:15)
丁寧な回答ありがとうございます。

あと一つだけ質問です、
ヘルパーメソッドとは何でしょうか?
初めて聞きました。
検索しても大した解説ページが見つかりませんでした。
http://d.hatena.ne.jp/qaz76/20110222/1299167727
ここにはそれらしき解説がありますがよく分かりませんでした。
 
引用返信 編集キー/
■80940 / inTopicNo.6)  Re[5]: コマンドプロンプトを実行する方法
□投稿者/ 魔界の仮面弁士 (832回)-(2016/08/22(Mon) 02:26:44)
No80939 (ボロンゴ さん) に返信
> ヘルパーメソッドとは何でしょうか?

「Process.Start メソッドを呼び出すことを支援するための自作メソッド」程度の意味です。
まぁ、あえて車輪の再発明(というか再実装)をせずとも、今回は Shell で十分な気もしますが。


> 検索しても大した解説ページが見つかりませんでした。
「ヘルパー」とは「手助けをするためのもの」。

たとえば一つの機能を呼び出すために、回りくどい書き方になってしまう場合や、
今回のように、複数行にわたって記述しなければならない処理があったときに、
それを簡潔に呼び出せるように用意した関数やメソッドやクラスのことだと
思っておいてください。


> 初めて聞きました。
下記のように、MSDN 中でも時々使われる用語ではあるのですが、改めて聞かれると
用語として説明されているものは見たことが無いですねそう言えば。


https://msdn.microsoft.com/ja-jp/library/ms227605%28vs.90%29.aspx
》 このセクションでは、データセットにデータを入力するヘルパー クラスを作成します。

https://msdn.microsoft.com/ja-jp/library/ms178208%28vs.100%29.aspx
》 最初の関数は、サーバーに実際に要求を行うヘルパー メソッドを呼び出します。
》 3 番目の関数は、サーバーに実際に要求を行うヘルパー関数です。

https://msdn.microsoft.com/ja-jp/library/ms178761.aspx
》 ……を使用して Excel オブジェクトのプロパティ値を設定するヘルパー メソッドを作成します。

https://support.microsoft.com/ja-jp/kb/205277#bookmark-20
》 通常、Visual Basic に用意されている組み込みのヘルパ関数を使用することで、Unicode から……

https://support.microsoft.com/en-us/kb/285879
》 ……the caller can call the "RunAsUser" helper function in the sample Visual Basic code below.

https://msdn.microsoft.com/ja-jp/library/mt608074.aspx
》 サンプルとヘルパー コードの使用
引用返信 編集キー/
■80947 / inTopicNo.7)  Re[6]: コマンドプロンプトを実行する方法
□投稿者/ ボロンゴ (10回)-(2016/08/22(Mon) 10:47:18)
ありがとうございます。

これって単に自分でShell関数と同じ引数の取り方の
クラスなりモジュールなりを作って
その中でProcess.Startを使うというものでしょうか?

引用返信 編集キー/
■80950 / inTopicNo.8)  Re[7]: コマンドプロンプトを実行する方法
□投稿者/ 魔界の仮面弁士 (836回)-(2016/08/22(Mon) 11:12:41)
No80947 (ボロンゴ さん) に返信
> これって単に自分でShell関数と同じ引数の取り方の
> クラスなりモジュールなりを作って
> その中でProcess.Startを使うというものでしょうか?

話としてはそうなりますが、まったく「同じ物」を自作するぐらいなら
Shell をそのまま使い続けたほうが良いと思いますよ。
Shell 機能に足りなかった何かを加える予定があるのなら別ですが。


たとえば、 No80937 の呼び出しを行うためのヘルパーなら、
下記のようなメソッドを用意することができます。

 Sub TaskKill(ByVal killTarget AS String)
   :
  psi.FileName = "TaskKill.exe"
  psi.Arguments = "/f /IM """ & killTarget & """"
  psi.WindowStyle = ProcessWindowStyle.Hidden
   :
 End Sub

TaskKill 専用とはなってしまいますが、その分、
呼び出し側のコードは簡素化されますね。

※Process のかわりに Shell でも可。
引用返信 編集キー/
■80951 / inTopicNo.9)  Re[8]: コマンドプロンプトを実行する方法
□投稿者/ ボロンゴ (11回)-(2016/08/22(Mon) 11:39:38)
納得しました。
どうもありがとうございます。
 
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -