プロセスが実行されているかどうかを確認するにはどうすればよいですか?


155

への参照を取得したときにSystem.Diagnostics.Process、プロセスが現在実行されているかどうかをどのようにして知ることができますか?

回答:


252

これは名前でそれを行う方法です:

Process[] pname = Process.GetProcessesByName("notepad");
if (pname.Length == 0)
  MessageBox.Show("nothing");
else
  MessageBox.Show("run");

すべてのプロセスをループして、後で操作するためにIDを取得できます。

Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist){
   Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}

これはまさに私が探していたものです。これは非常に古い投稿ですが、これがどのように有効なC#であるかを説明してください。私はそれを疑っていない、私はそれが機能するのを見るが、{}なしでなければ他に見たことがない。
MatthewD 2015年

4
@MatthewD:if/else長さが1行しかないC#ステートメントでは、ブロックステートメントを示すために中括弧を付ける必要はありません。これはforeachand forステートメントにも当てはまります。つまり、コーディングスタイルです。
Hallmanac

私もこれについていくつかの調査を行い、その情報を見つけましたが、その情報は表示されませんでしたfor。c#.net devの年と私はこのスタイルを見たことがありません。彼らが言うように、「あなたは毎日何か新しいことを学びます」。投稿と返信をありがとう..
MatthewD 2015年

3
@MatthewDええ、これは実際にはほとんどの言語(Javaなど)に当てはまります。一般に、このような1行を避け、常に中かっこを付けることをお勧めします。将来、ステートメントを追加する必要が生じる可能性が常にあるためです。ただし、このような場合、必要なステートメントが1つだけであると100%確信していれば、構文的には問題ありません。
David Mordigal 2016

1
プロセスが見つからない場合は、拡張機能を削除してみてください。(例:.exe)
DxTx 2018

28

これは、反射板を使用した後に見つけた最も簡単な方法です。そのための拡張メソッドを作成しました。

public static class ProcessExtensions
{
    public static bool IsRunning(this Process process)
    {
        if (process == null) 
            throw new ArgumentNullException("process");

        try
        {
            Process.GetProcessById(process.Id);
        }
        catch (ArgumentException)
        {
            return false;
        }
        return true;
    }
}

Process.GetProcessById(processId)この方法は、呼び出すProcessManager.IsProcessRunning(processId)メソッドをして投げるArgumentExceptionのプロセスが存在しない場合には。どういうわけか、ProcessManagerクラスは内部です...


これは本当に良い答えでした。ただし、引数null例外を通過させるべきではありません(null参照例外がスローされ、例外に対して何もしなかったためです。また、Start()を呼び出さなかった場合は、InvalidOperationExceptionが発生します。メソッドまたはclose()メソッドを呼び出しました。これら2つの状況を説明するために別の回答を投稿しました
Aelphaeis

16

同期ソリューション:

void DisplayProcessStatus(Process process)
{
    process.Refresh();  // Important


    if(process.HasExited)
    {
        Console.WriteLine("Exited.");
    }
    else
    {
        Console.WriteLine("Running.");
    } 
}

非同期ソリューション:

void RegisterProcessExit(Process process)
{
    // NOTE there will be a race condition with the caller here
    //   how to fix it is left as an exercise
    process.Exited += process_Exited;
}

static void process_Exited(object sender, EventArgs e)
{
   Console.WriteLine("Process has exited.");
}

6
最初のオプションの場合:プロセスが最初に開始されたかどうかをどうやって知ることができますか?
reshefm 2008年

8

reshefmはかなりいい答えをしました。ただし、プロセスが最初から開始されなかった状況は考慮されていません。

ここに彼が投稿したものの修正版があります。

    public static bool IsRunning(this Process process)
    {
        try  {Process.GetProcessById(process.Id);}
        catch (InvalidOperationException) { return false; }
        catch (ArgumentException){return false;}
        return true;
    }

彼のArgumentNullExceptionは実際にはnull参照例外であると想定されているので削除しましたが、それはとにかくシステムによってスローされ、プロセスが開始されなかったか、close()メソッドが処理する。


個人的には、ログに記録された例外を確認するときに、NullReferenceExceptionよりもArgumentNullExceptionの方が見たいと思っています。
Sean

1
@Sean通常は同意しますが、これは拡張メソッドです。構文を考えると、nullポインタ例外をスローする方が適切だと思います。nullオブジェクトのメソッドの呼び出しとの一貫性が増すだけです。
Aelphaeis

これにより毎回FirstHandledExceptionイベントハンドラーがトリガーされます。あなたのログをバディにスパムする方法。
レイテンシ

6

これはワンライナーである必要があります:

public static class ProcessHelpers {
    public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0;
}

3

これは、この関数の信頼性に依存します。あなたが持っている特定のプロセスインスタンスがまだ実行中であり、100%の精度で利用可能であるかどうかを知りたい場合、あなたは運が悪いです。その理由は、管理されたプロセスオブジェクトからプロセスを識別する方法が2つしかないためです。

1つ目はプロセスIDです。残念ながら、プロセスIDは一意ではなく、リサイクルできます。一致するIDのプロセスリストを検索すると、同じIDのプロセスが実行されていることがわかりますが、必ずしもプロセスとは限りません。

2番目の項目はプロセスハンドルです。Idと同じ問題がありますが、操作がより厄介です。

中程度の信頼性を求めている場合は、同じIDのプロセスについて現在のプロセスリストを確認するだけで十分です。


1

Process.GetProcesses()行く方法です。ただし、プロセスの実行方法(タイトルバーの有無にかかわらず、サービスまたは通常のアプリとして)に応じて、プロセスを見つけるために1つ以上の異なる基準を使用する必要がある場合があります。


このメソッドをループに入れると、多くのCPUサイクルがかかります。GetProcessByName()またはGetProcessByID()を使用することをお勧めします。
Hao Nguyen

0

たぶん(おそらく)私は質問を間違って読んでいますが、Processオブジェクトによって表されるプロセスが終了したことを通知するHasExitedプロパティを探していますか(通常かどうかにかかわらず)。

参照しているプロセスにUIがある場合、Respondingプロパティを使用して、UIが現在ユーザー入力に応答しているかどうかを判断できます。

また、ブロックする場合は、EnableRaisingEventsを設定して、Exitedイベント(非同期に送信される)を処理するか、WaitForExit()を呼び出すこともできます。


0

必要なプロセスのプロセスインスタンスを1回インスタンス化し、その.NETプロセスオブジェクトを使用してプロセスを追跡し続けることができます(追跡していたプロセスが停止した場合でも、その.NETオブジェクトで明示的にCloseを呼び出すまで追跡し続けます) [これは、プロセスの終了時間、別名ExitTimeなどを提供できるようにするためです])

引用http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx

関連するプロセスが終了すると(つまり、正常終了または異常終了によってオペレーティングシステムによってシャットダウンされると)、システムはプロセスに関する管理情報を格納し、WaitForExitを呼び出したコンポーネントに戻ります。次に、プロセスコンポーネントは、終了したプロセスへのハンドルを使用して、ExitTimeを含む情報にアクセスできます。

関連するプロセスが終了したため、コンポーネントのHandleプロパティは既存のプロセスリソースを指していません。代わりに、ハンドルは、プロセスリソースに関するオペレーティングシステムの情報にアクセスするためにのみ使用できます。システムは、プロセスコンポーネントによって解放されていない終了したプロセスへのハンドルを認識しているため、プロセスコンポーネントが具体的にリソースを解放するまで、メモリにExitTimeおよびHandle情報を保持します。このため、プロセスインスタンスに対してStartを呼び出すときはいつでも、関連するプロセスが終了し、それに関する管理情報が不要になったときに、Closeを呼び出します。Closeは、終了したプロセスに割り当てられたメモリを解放します。


0

私はコインコインの解決策を試しました:
ファイルを処理する前に、一時ファイルとしてコピーして開きます。
完了したら、アプリケーションがまだ開いている場合はアプリケーションを閉じ、一時ファイルを削除します
。Process変数を使用し、後で確認するだけです。

private Process openApplication;  
private void btnOpenFile_Click(object sender, EventArgs e) {  
    ...
    // copy current file to fileCache  
    ...  
    // open fileCache with proper application
    openApplication = System.Diagnostics.Process.Start( fileCache );  
}

後でアプリケーションを閉じます。

 ...   
openApplication.Refresh(); 

// close application if it is still open       
if ( !openApplication.HasExited() ) {
    openApplication.Kill();  
}

// delete temporary file  
System.IO.File.Delete( fileCache );

動作します(これまでのところ)


3
ではopenApplication.HasExited()、HasExitedは関数ではありません。正しい方法はでしょうopenApplication.HasExited
caiosm1005 2013

0

プロセスIDによる既存のプロセスのチェックに関して.NetフレームワークからサポートされているAPIにもかかわらず、これらの関数は非常に低速です。Process.GetProcesses()またはProcess.GetProcessById / Name()を実行するには、大量のCPUサイクルがかかります。

IDで実行中のプロセスを確認するより迅速な方法は、ネイティブAPI OpenProcess()を使用することです。リターンハンドルが0の場合、プロセスは存在しません。ハンドルが0以外の場合、プロセスは実行中です。許可を得ているため、このメソッドが常に100%機能するという保証はありません。


0

他にも部分的に対処しているように見えるため、これに関連する多くの問題があります。

  • インスタンスメンバーは、スレッドセーフであるとは限りません。オブジェクトのプロパティを評価しようとしているときに、スナップショットの存続期間中に発生する可能性のある競合状態があることを意味します。
  • プロセスハンドルは、このプロパティおよび他のそのようなプロパティを評価するためのアクセス許可が許可されていない場合、ACCESS DENIEDに対してWin32Exceptionをスローします。
  • IS N'T RUNNINGステータスの場合、そのプロパティの一部を評価しようとすると、ArgumentExceptionも発生します。

他の人が言及したプロパティが内部であるかどうかにかかわらず、許可が許せば、リフレクションを介してそれらから情報を取得できます。

var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);

あなたはWin32コードをピンボークすることができます スナップショットのか、遅いWMIを使用できます。

HANDLE CreateToolhelp32Snapshot(
  DWORD dwFlags,
  DWORD th32ProcessID
);

別のオプションは、OpenProcess / CloseProcessですが、例外は以前と同じようにスローされますが、同じ問題が発生します。

WMIの場合-OnNewEvent.Properties ["?"]:

  • 「ParentProcessID」
  • 「ProcessID」
  • 「プロセス名」
  • 「SECURITY_DESCRIPTOR」
  • "セッションID"
  • 「シド」
  • 「TIME_CREATED」

0
string process = "notepad";
if (Process.GetProcessesByName(process).Length == 0)
{
    MessageBox.Show("Working");
}
else
{
    MessageBox.Show("Not Working");
}

また、毎回プロセスをチェックするためにタイマーを使用することができます


3
逆にならないでしょうか?長さ== 0の場合、機能しないことを意味しますか?
ジェイジェイコブス

答えはパトリックデジャルダンと同じです:stackoverflow.com/a/262291/7713750
Rekshino

その長さ> 0に関する他の方法は、プロセスが見つかったことを意味します。
HaseeB Mir

これにはエラーがあるかもしれませんが(length == 0が表示されるはずですNot Working)、それでもジョブは完了します。
モモロ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.