53

次のようなコードを使用して、プログラムでInternetExplorerを起動しています。

ProcessStartInfo startInfo = new ProcessStartInfo("iexplore.exe");
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = "http://www.google.com";
Process ieProcess = Process.Start(startInfo);

これにより、Windowsタスクマネージャーに表示される2つのプロセスが生成されます。次に、次の方法でプロセスを強制終了しようとします。

ieProcess.Kill();

これにより、タスクマネージャのプロセスの1つがシャットダウンされ、もう1つは残ります。子プロセスを持つプロパティをチェックしようとしましたが、見つかりませんでした。他のプロセスも強制終了するにはどうすればよいですか?より一般的には、Process.Startで開始するプロセスに関連付けられているすべてのプロセスをどのように強制終了しますか?

4

11 に答える 11

80

これは私にとって非常にうまくいきました:

/// <summary>
/// Kill a process, and all of its children, grandchildren, etc.
/// </summary>
/// <param name="pid">Process ID.</param>
private static void KillProcessAndChildren(int pid)
{
    // Cannot close 'system idle process'.
    if (pid == 0)
    {
        return;
    }
    ManagementObjectSearcher searcher = new ManagementObjectSearcher
            ("Select * From Win32_Process Where ParentProcessID=" + pid);
    ManagementObjectCollection moc = searcher.Get();
    foreach (ManagementObject mo in moc)
    {
        KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"]));
    }
    try
    {
        Process proc = Process.GetProcessById(pid);
        proc.Kill();
    }
    catch (ArgumentException)
    {
        // Process already exited.
    }
}

2016年4月26日更新

Visual Studio 2015 Update 2でテスト済みWin7 x64。3年前と同じように今でもうまく機能しています。

2017年11月14日更新

システムアイドルプロセスのチェックを追加if (pid == 0)

更新2018-03-02

名前空間への参照を追加する必要がありSystem.Managementます。以下の@MinimalTechからのコメントを参照してください。ReSharperがインストールされている場合は、これを自動的に実行するように提案されます。

2018年10月10日更新

これの最も一般的な使用例は、独自のC#プロセスが開始した子プロセスを強制終了することです。

この場合、より良い解決策は、C#内でWin32呼び出しを使用して、生成されたプロセスを子プロセスにすることです。これは、親プロセスが終了すると、子プロセスがWindowsによって自動的に閉じられることを意味します。これにより、上記のコードが不要になります。コードを投稿してほしい場合はお知らせください。

于 2012-05-01T19:12:47.657 に答える
29

dotnetコアソリューションが必要な場合は、

Dotnetコア3.0

process.Kill(true);

公式ドキュメントを参照してください

Dotnetコア2.0

.Net 2.0の場合、dotnet cliは、上記のtaskillに基づく実装と、unixベースのシステム用の再帰的なpgrep/killを考案しました。完全な実装はgithubにあります。残念ながら、クラスは内部であるため、コードベースにコピーする必要があります。

子プロセスのリスト(再帰的に実行する必要があります):

$"pgrep -P {parentId}"

プロセスでキル:

$"kill -TERM {processId}"
于 2017-08-14T04:56:55.877 に答える
13

私はここに提示されたソリューションのいずれのファンでもありません。

これが私が思いついたものです:

private static void EndProcessTree(string imageName)
{
    Process.Start(new ProcessStartInfo
    {
        FileName = "taskkill",
        Arguments = $"/im {imageName} /f /t",
        CreateNoWindow = true,
        UseShellExecute = false
    }).WaitForExit();
}

使い方:

EndProcessTree("chrome.exe");
于 2017-02-19T21:13:03.430 に答える
10

Process.CloseMainWindow()プロセスのメインウィンドウにメッセージを送信するを呼び出す必要があります。ユーザーに「X」閉じるボタンまたはファイル|をクリックさせると考えてください。メニュー項目を終了します。

すべてのプロセスを強制終了するよりも、InternetExplorerにメッセージを送信して自身を閉じる方が安全です。これらのプロセスは何でも実行している可能性があり、将来の実行で重要になる可能性のある処理を実行している最中にIEを強制終了する前に、IEにその処理を実行させて終了させる必要があります。これは、あなたが殺したどんなプログラムにも当てはまります。

于 2012-11-14T10:07:11.893 に答える
9

興味のある方は、他のページの回答を少し修正してみました。これは、静的メソッドを持つ自己完結型のクラスです。適切なエラー処理またはロギングがありません。自分のニーズに合わせて変更します。ルートプロセスをKillProcessTreeに提供することでそれが可能になります。

class ProcessUtilities
{
    public static void KillProcessTree(Process root)
    {
        if (root != null)
        {
            var list = new List<Process>();
            GetProcessAndChildren(Process.GetProcesses(), root, list, 1);

            foreach (Process p in list)
            {
                try
                {
                    p.Kill();
                }
                catch (Exception ex)
                {
                    //Log error?
                }
            }
        }
    }

    private static int GetParentProcessId(Process p)
    {
        int parentId = 0;
        try
        {
            ManagementObject mo = new ManagementObject("win32_process.handle='" + p.Id + "'");
            mo.Get();
            parentId = Convert.ToInt32(mo["ParentProcessId"]);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
            parentId = 0;
        }
        return parentId;
    }

    private static void GetProcessAndChildren(Process[] plist, Process parent, List<Process> output, int indent)
    {
        foreach (Process p in plist)
        {
            if (GetParentProcessId(p) == parent.Id)
            {
                GetProcessAndChildren(plist, p, output, indent + 1);
            }
        }
        output.Add(parent);
    }
}
于 2011-05-07T15:25:31.283 に答える
6

別の解決策は、taskillコマンドを使用することです。アプリケーションで次のコードを使用します。

public static void Kill()
{
    try
    {
            ProcessStartInfo processStartInfo = new ProcessStartInfo("taskkill", "/F /T /IM your_parent_process_to_kill.exe")
            {
                WindowStyle = ProcessWindowStyle.Hidden,
                CreateNoWindow = true,
                UseShellExecute = false,
                WorkingDirectory = System.AppDomain.CurrentDomain.BaseDirectory,
                RedirectStandardOutput = true,
                RedirectStandardError = true
            };
            Process.Start(processStartInfo);
    }
    catch { }
}
于 2015-09-15T20:27:38.393 に答える
4

IE8またはIE9を使用していますか?新しいマルチプロセスアーキテクチャにより、これは絶対に複数のプロセスを開始します。とにかく、プロセスツリーを取得してそれを強制終了するためのこの他の答えを見てください。

于 2011-05-05T17:28:36.320 に答える
3

非常に便利なもう1つのアプローチは、ジョブオブジェクトにWindowsAPIを使用することです。プロセスをジョブオブジェクトに割り当てることができます。このようなプロセスの子プロセスは、同じジョブオブジェクトに自動的に割り当てられます。

ジョブオブジェクトに割り当てられたすべてのプロセスは、たとえば次のようなTerminateJobObjectを使用して一度に強制終了できます。

現在ジョブに関連付けられているすべてのプロセスを終了します。

この回答のC#の例(この回答に基づく)では、代わりにJOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSEフラグを使用しています。

ジョブへの最後のハンドルが閉じられたときに、ジョブに関連付けられているすべてのプロセスを終了させます。

于 2017-05-17T09:42:01.387 に答える
1

.NET Core 3.0には、そのためのメソッド、つまり既存のメソッドの新しいオーバーロードProcess.Kill()があります。IOWは、typeprocess.Kill(true)の変数を実行すると、そのすべての子孫でプロセスが強制終了されます。当然、これはクロスプラットフォームです。processProcess

于 2019-09-30T22:33:20.773 に答える
0

PowerShellから起動したときにInternetExplorerを適切に閉じるにはどうすればよいですか?

上記のスレッドで、これはWin7のバグが原因であるとコメントしている人もいます(他のバージョンのWindowsを使用しているユーザーには発生しないようです)。マイクロソフトのページを含むインターネット上の多くのページは、ユーザーエラーを主張し、すべての子プロセスも閉じるように想定されているIEオブジェクトで利用可能なquitメソッドを使用するように指示します(Win8 / XPなどで報告されています)

私の側では、それはユーザーエラーであったことを認めなければなりません。私はwin7にいますが、quitメソッドが機能しなかったのは、コーディングのエラーが原因でした。つまり、宣言時にIEオブジェクトを作成し、その後コードで別の(同じオブジェクトにアタッチされた)オブジェクトを作成していました...問題に気付いたとき、親子の殺害ルーチンをハッキングして作業を終えるところだったのです。

IEの機能により、親として生成したprocessIDは、作成していない他のウィンドウ/サブプロセスにアタッチされる可能性があります。quitを使用します。また、ユーザー設定(終了時の空のキャッシュなど)によっては、プロセスがタスクを完了して閉じるまでに数分かかる場合があることに注意してください。

于 2015-11-20T19:31:28.723 に答える
0

ドキュメントによると

Killメソッドは非同期で実行されます。Killメソッドを呼び出した後、WaitForExitメソッドを呼び出してプロセスが終了するのを待つか、HasExitedプロパティをチェックしてプロセスが終了したかどうかを確認します。

ProcessStartInfo startInfo = new ProcessStartInfo("iexplore.exe");
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = "http://www.google.com";
Process ieProcess = Process.Start(startInfo);
ieProcess.Kill();
ieProcess.WaitForExit();
于 2020-08-12T01:35:23.350 に答える