主婦と.NETと犬のぶろぐ

奥様 と プログラム と お犬様 の 楽しい日常

目次

Blog 利用状況

ニュース

書庫

日記カテゴリ

Process(System.Diagnostics.Process)

いつも↓こちらの様に Start して WaitForExit といういたってノーマルな使い方をしていますが、
@IT ほかのアプリケーションを実行してその終了を待つには?
調べてみるといろんなプロパティがあるもんですねぇ。

今回は、自分で作ったアプリケーション(ProcessTest)→自分で作ったアプリケーション(D:\ProcessTestApp.exe)と通信いたしました。

■参考文献
Process クラス
ProcessStartInfo クラス

■実行画像
画面の起動と同時に ProcessTestApp.exe を起動して、Button を押下すると ComboBox で選択されている値を ProcessTestApp.exe へ送ります。
Process
ProcessTestApp.exe へ "e" を送ったところ。
Process アプリケーションの終了

■ProcessTest

Public Class ProcessTest

Private m_timer As System.Windows.Forms.Timer
Private Sub ProcessTest_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' '' 実行しているプロセスの一覧を取得する 'Dim procs As System.Diagnostics.Process() = System.Diagnostics.Process.GetProcesses() 'For Each proc As System.Diagnostics.Process In procs ' Console.WriteLine(proc.ProcessName) 'Next
'' ProcessInfo と Process の設定 Dim procStartInfo As ProcessStartInfo = New ProcessStartInfo() With procStartInfo ' 起動するファイル名 .FileName = "D:\ProcessTestApp.exe" ' 引数 .Arguments = "ふじこ えでん オット" ' エラーの出力を Process オブジェクト.StandardError で取れるようにする .RedirectStandardError = True ' 入力を Process オブジェクト.StandardInput で取れるようにする .RedirectStandardInput = True ' 出力を Process オブジェクト.StandardOutput で取れるようにする .RedirectStandardOutput = True ' リダイレクトするので OS のシェルは使用しない .UseShellExecute = False ' 新しいウィンドウは作らない .CreateNoWindow = True .WindowStyle = ProcessWindowStyle.Hidden End With
With Me.Process1 ' ProcessStartInfo を関連付け .StartInfo = procStartInfo ' Process 終了時に Exited イベントを発生させるか否か(既定:False) ' OnExited メソッドを使うとプログラムから Exited イベントの発生が可能 .EnableRaisingEvents = True AddHandler .Exited, AddressOf OnProcessExited '' 待機状態から抜けたときにプロセスの優先順位を動的に上げるか否か(既定:False) '.PriorityBoostEnabled = False ' Exited イベントのイベント ハンドラ呼び出しをマーシャリングするために使用する ISynchronizeInvoke .SynchronizingObject = Me ' 各ストリームに書き出された時のハンドラを追加する AddHandler .ErrorDataReceived, AddressOf OnErrorDataRecieved AddHandler .OutputDataReceived, AddressOf OnOutputDataReceived
' 開始 .Start() '' Start のいろいろ(全部 Shared メソッド→インスタンス生成) 'Dim pass As System.Security.SecureString = New System.Security.SecureString() 'pass.AppendChar("p"c) : pass.AppendChar("a"c) : pass.AppendChar("s"c) : pass.AppendChar("s"c) ''Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start("ファイル名", "UserName", pass, "Domain") 'Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start("ファイル名", "引数", "UserName", pass, "Domain") 'Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start("ファイル名") 'Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start("ファイル名", "引数") 'Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start(procStartInfo)
' プロセスがアイドル状態になるまで待機する ' (UI とメッセージ ループを持つプロセスのみ) '.WaitForInputIdle() ' 終了するまで無期限に待機する '.WaitForExit() ' 非同期読み取り操作の開始 .BeginErrorReadLine() .BeginOutputReadLine() End With
'' Timer の設定 Me.m_timer = New System.Windows.Forms.Timer() Me.m_timer.Interval = 5000 AddHandler Me.m_timer.Tick, AddressOf Timer_Tick Me.m_timer.Start()
'' 入力部品の設定 Me.ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList Me.ComboBox1.Items.AddRange(New String() {"e", "x", "z"}) AddHandler Button2.Click, AddressOf Send Dim tip As ToolTip = New ToolTip() tip.IsBalloon = True tip.SetToolTip(Me.Button2, "e:raise exception x:exit0 z:exit1") End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click If Me.Process1.HasExited Then Return Me.m_timer.Stop() With Me.Process1 '' メインウィンドウが存在する場合に WM_CLOSE を送信 '.CloseMainWindow() ' 即時中断・メインウィンドウがない場合はこれで終了する .Kill() '' プロセスに関連付けられているリソースの解放 '.Close() End With End Sub
Private Sub Send(ByVal sender As Object, ByVal e As EventArgs) If Me.Process1.HasExited Then Return ' ComboBox で選択された値を入力 Me.Process1.StandardInput.WriteLine(DirectCast(Me.ComboBox1.SelectedItem, String)) End Sub
Private Sub Timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) If Me.Process1.HasExited Then ' 正常にしろ異常にしろ Process が終了してたら timer を Off Me.m_timer.Stop() Return End If
With Me.Process1 ' PriorityClass から算出される基本優先順位 Console.WriteLine("BasePriority:" & .BasePriority.ToString()) Console.WriteLine("PriorityClass:" & .PriorityClass.ToString()) ' プロセス ID Console.WriteLine("Id:" & .Id.ToString()) ' ハンドル Console.WriteLine("Handle:" & .Handle.ToString()) Console.WriteLine("MainWindowHandle:" & .MainWindowHandle.ToString()) ' プロセスを実行しているコンピュータ名 Console.WriteLine("MachineName:" & .MachineName) ' メインウィンドウのキャプション Console.WriteLine("MainWindowTitle:" & .MainWindowTitle) ' 名前 Console.WriteLine("ProcessName:" & .ProcessName) ' 関連付けられたプロセスのスレッドを実行できるプロセッサを示すビットマスク Console.WriteLine("ProcessorAffinity:" & .ProcessorAffinity.ToString()) ' ユーザーインターフェースが応答するか否か Console.WriteLine("Responding:" & .Responding.ToString()) ' ターミナル サービス セッション識別子 Console.WriteLine("SessionId:" & .SessionId.ToString())
' メインモジュール(ProcessModule 型) Console.WriteLine("MainModule:" & .MainModule.ModuleName) ' 読み込まれたモジュール全て Dim modules As ProcessModuleCollection = .Modules For Each md As System.Diagnostics.ProcessModule In modules Console.WriteLine("Module:" & md.ModuleName) Next ' Thread For Each th As ProcessThread In .Threads Console.WriteLine("Thread:" & th.Id.ToString()) Next
' プロセスのワーキング セット(物理 RAM メモリ内でプロセスが現在参照できるメモリ ページのセット) Console.WriteLine("MaxWorkingSet:" & .MaxWorkingSet.ToString()) Console.WriteLine("MinWorkingSet:" & .MinWorkingSet.ToString())
' 割り当てられたページングされないシステム メモリの量 ' NonpagedSystemMemorySize は Obsolete Console.WriteLine("NonpagedSystemMemorySize64:" & .NonpagedSystemMemorySize64.ToString()) ' 割り当てられたページングされるシステム メモリの量 ' PagedMemorySize は Obsolete Console.WriteLine("PagedMemorySize64:" & .PagedMemorySize64.ToString()) ' 割り当てられたページング可能なシステム メモリの量 ' PagedSystemMemorySize は Obsolete Console.WriteLine("PagedSystemMemorySize64:" & .PagedSystemMemorySize64.ToString()) ' 使用される仮想メモリ ページング ファイル内のメモリの最大量 ' PeakPagedMemorySize は Obsolete Console.WriteLine("PeakPagedMemorySize64:" & .PeakPagedMemorySize64.ToString()) ' 使用される仮想メモリの最大量 ' PeakVirtualMemorySize は Obsolete Console.WriteLine("PeakVirtualMemorySize64:" & .PeakVirtualMemorySize64.ToString()) ' 使用される物理メモリの最大量 ' PeakWorkingSet は Obsolete Console.WriteLine("PeakWorkingSet64:" & .PeakWorkingSet64.ToString()) ' 割り当てられたプライベート メモリの量 ' PrivateMemorySize は Obsolete Console.WriteLine("PrivateMemorySize:" & .PrivateMemorySize64.ToString()) ' 割り当てられた仮想メモリの量 ' VirtualMemorySize は Obsolete Console.WriteLine("VirtualMemorySize64:" & .VirtualMemorySize64.ToString())
' カーネルコマンドを実行するための特権時間に費やした時間(TimeSpan 型) Console.WriteLine("PrivilegedProcessorTime:" & .PrivilegedProcessorTime.TotalMilliseconds.ToString()) ' 上記に該当する部分以外のコードを実行するのに費やした時間(TimeSpan 型) Console.WriteLine("UserProcessorTime:" & .UserProcessorTime.TotalMilliseconds.ToString()) ' PrivilegedProcessorTime + UserProcessorTime Console.WriteLine("TotalProcessorTime:" & .TotalProcessorTime.TotalMilliseconds.ToString()) End With
End Sub
' プロセスが終了した時に発生 Private Sub OnProcessExited(ByVal sender As Object, ByVal e As System.EventArgs) With Me.Process1 ' 終了コード System.Diagnostics.Debug.WriteLine("ExitCode:" & .ExitCode.ToString()) ' 開始時刻 System.Diagnostics.Debug.WriteLine("StartTime:" & .StartTime.ToString("yyyy/MM/dd HH:mm:ss")) ' 終了時間 System.Diagnostics.Debug.WriteLine("ExitTime:" & .ExitTime.ToString("yyyy/MM/dd HH:mm:ss")) End With End Sub
' StandardError に書き込まれた時に発生 Private Sub OnErrorDataRecieved(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) System.Diagnostics.Debug.WriteLine("OnErrorDataRecieved:" & e.Data) End Sub
' StandardOutput に書き込まれた時に発生 Private Sub OnOutputDataReceived(ByVal sender As Object, ByVal e As System.Diagnostics.DataReceivedEventArgs) System.Diagnostics.Debug.WriteLine("OnOutputDataReceived:" & e.Data) End Sub End Class

■ProcessTestApp.exe のコード

'' ProcessTest 用
Module Module1
    Function Main(ByVal args As String()) As Integer
        If Not args Is Nothing Then
            Console.Write("■ProcessTestApp■Arguments is :")
            For Each arg As String In args
                Console.Write(arg & " ")
            Next
            Console.WriteLine()
        End If

Dim bk As System.ComponentModel.BackgroundWorker = _ New System.ComponentModel.BackgroundWorker() AddHandler bk.DoWork, AddressOf DoWork AddHandler bk.RunWorkerCompleted, AddressOf RunWorkerCompleted bk.WorkerSupportsCancellation = True ' Cancel 可能に bk.RunWorkerAsync()
Console.WriteLine("■ProcessTestApp■e:raise exception x:exit0 z:exit1") Dim inputed As String = Console.ReadLine().ToLower() bk.CancelAsync() Select Case inputed Case "e" Throw New ApplicationException("えらーが発生した") Case "z" System.Environment.Exit(1) ' 終了コード 1 Case Else System.Environment.Exit(0) ' 終了コード 0 End Select End Function
' 非同期の仕事 Private Sub DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Dim bk As System.ComponentModel.BackgroundWorker = _ DirectCast(sender, System.ComponentModel.BackgroundWorker)
For counter As Integer = 1 To 100 If bk.CancellationPending Then ' Cancel された e.Cancel = True Return End If System.Threading.Thread.Sleep(1000) Console.WriteLine("□ProcessTestApp□DoWork :" & counter.ToString()) Next End Sub
' 非同期の仕事が終わったとき Private Sub RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) If e.Cancelled Then Console.WriteLine("□ProcessTestApp□RunWorkerCompleted :Cancelled") ElseIf Not e.Error Is Nothing Then Console.WriteLine("□ProcessTestApp□RunWorkerCompleted :Error Occurred") Else Console.WriteLine("□ProcessTestApp□RunWorkerCompleted :Completed") End If End Sub End Module

投稿日時 : 2007年3月9日 10:53

Feedback

# re: Process(System.Diagnostics.Process) 2007/03/09 11:12 ぽぴ王子

> ' 新しいウィンドウでやるかどうか
> .CreateNoWindow = True

ここですが。

> ' 新しいウィンドウは作らない
> .CreateNoWindow = True

こんな感じのコメントの方がいいかな?とか思ったり。
NoWindow って否定なのに意外と見落としがちで、True とか書いてあると
新しいウィンドウでやるんだね父ちゃん!(誰が父ちゃんだ)とか
思ったりしちゃいそうです。

もひとつ。

> ProcessTestApp.exe へ "e" を送ったところ。

で、おもむろにエラー画面があってびっくり(笑)
よくよくコードを読むと、"e" を送信したら ProcessTestApp.exe 側で
自発的にエラーを発生させるようになってるんですね。

何か不具合が起きた画面を載せているのかと思って一瞬焦ったのは内緒。

# re: Process(System.Diagnostics.Process) 2007/03/09 11:24 なおこ(・∀・)

>> 王子
アドバイスありがとうございます。
直しますた!

> エラー画面
おほほ。

# re: Process(System.Diagnostics.Process) 2007/03/09 15:39 とりこびと

おもむろにエラー画面があってびっくりしたとりこびとが来ましたよ。

ちなみに 'e' を見ると EventArgsが真っ先に浮かびますね
あ、'ex'とばしてちゃバレバレですね。orz

>こんな感じのコメントの方がいいかな?とか思ったり。
ぽぴ王子と愉快な家来たち」Day モードかなw

# re: Process(System.Diagnostics.Process) 2007/03/09 19:38 なおこ(・∀・)

>> とりこびとさん
ややや。ついにわんくまに入ったんですね。

> 'e'
実はあんまり考えてません。
テストしたりするのに何文字も入力するのが面倒なので
一文字にしただけです。

# re: Process(System.Diagnostics.Process) 2007/03/10 15:47 渋木宏明(ひどり)

起動する相手が GUI アプリであることが分かっている場合、相手に何か手出しをする前に Process.WaitForInputIdle() した方が良いケースが多いです。
(最近のCPUは速いから、しなくても大丈夫な場合がほとんどでしょうけど)

タイトル  
名前  
Url
コメント