1

私はプログラミングが初めてです。スレッドを起動するフォーム アプリケーションがあります。そこから 4 つの新しいスレッドが立ち上げられます。これらの各スレッドは、次のような一連のコマンド ライン プロセスを実行します。

ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.WorkingDirectory ="C:\\BLA\\bin_windows";
        startInfo.UseShellExecute = false;
        startInfo.RedirectStandardOutput = true;
        startInfo.CreateNoWindow = true;

            startInfo.FileName = "SomeProcess"
            Process p = Process.Start(startInfo);
        p.WaitForExit();

フォーム アプリケーションが閉じられると、最初のスレッド (4 つの個別のスレッドではなく) が中止されます。今私の質問は、フォームを閉じたときにプロセス「p」を強制的に終了させる方法です?? 私は次のことを試しました:

    foreach (Process p in System.Diagnostics.Process.GetProcessesByName("SomeProcess"))
    {
        try
        {
            p.Kill();
            p.WaitForExit(); // possibly with a timeout
        }
        catch
        { continue; }
    } 

ただし、このアプローチは私には少し残忍に思え、常にうまく機能するとは限りません...自分で起動したプロセスだけを特定して終了する方法はありますか? どんな提案でも大歓迎です。ありがとう

4

3 に答える 3

2

実行したプロセスをほとんど制御できません。それらを殺すことは一つの方法です。WM_CLOSEプロセスがウィンドウ化されたアプリケーション (つまり、ウィンドウがある) である場合は、ウィンドウの閉じるボタンをクリックするのと同じメッセージをプロセスに送信してみることができます。繰り返しますが、アプリケーションには、表示または非表示のウィンドウが必要です。そのため、すべてのアプリケーションで機能するとは限りません。ほとんどのアプリケーションには、見えなくてもウィンドウがあります。

const uint WM_CLOSE = 0x10;

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, uint uMsg, int wParam, int lParam);

Process p = Process.GetProcessesByName("notepad").FirstOrDefault();
if(p != null)
{
    IntPtr hWnd = p.MainWindowHandle;
    SendMessage(hWnd, WM_CLOSE, 0, 0);
}

生成したプロセスのみを強制終了/閉じるには、Processオブジェクトを保持するか、少なくともp.MainWindowHandle私が提供したアプローチを使用する場合。そのためには、クラスにタイプConcurrentBag<Process>(またはConcurrentBag<IntPtr>) のパブリック プロパティを用意します。すでにスレッドセーフです。

編集

誰かが指摘したように、これを実行してプロセスのメイン ウィンドウを閉じることができます。

p.CloseMainWindow()
于 2012-04-20T19:25:25.403 に答える
0

プログラムを一度に2回実行することが想定されていない場合は、シングルトンで何らかのプロセスマネージャーを使用できます。

internal sealed class ProcessManager
{
    private readonly IList<Process> processes;

    #region Singleton

    private static readonly object locker = new object();
    private static volatile ProcessManager instance;

    private ProcessManager()
    {
        processes = new List<Process>();
    }

    public static ProcessManager Instance
    {
        get
        {
            if (instance == null)
            {
                lock (locker)
                {
                    if (instance == null)
                    {
                        instance = new ProcessManager();
                    }
                }
            }

            return instance;
        }
    }

    #endregion

    public void AddProcess(Process process)
    {
        lock(processes)
        {
            processes.Add(process);
        }
    }

    public void TerminateAll()
    {
        lock(processes)
        {
            foreach (Process p in processes)
            {
                try
                {
                    p.Kill();
                    p.WaitForExit(); // possibly with a timeout
                }
                catch
                {
                     continue;
                }
            }
        }
    }
}

使用法:

ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.WorkingDirectory ="C:\\BLA\\bin_windows";
    startInfo.UseShellExecute = false;
    startInfo.RedirectStandardOutput = true;
    startInfo.CreateNoWindow = true;

        startInfo.FileName = "SomeProcess"
        Process p = Process.Start(startInfo);
        ProcessManager.Instance.AddProcess(p);
    p.WaitForExit();

プログラムに静的なものが必要ない場合(たとえば、そのインスタンスをいくつか持つことができます)、このクラスを使用できますが、シングルトンはなく、すべてのスレッドにその単一のインスタンスを与えます。

于 2012-04-20T19:45:34.617 に答える
0

プロセスを閉じたい場合は、P/Invoke を実行して WM_CLOSE メッセージを送信する必要はありません。Process インスタンスでCloseMainWindow()メソッドを呼び出すだけです (WM_CLOSE が送信されます)。その後、 Close()メソッドを使用してフォローアップし、ローカル ビューを解放できます。

開始したプロセスを追跡することも非常に簡単です。

public static ConcurrentBag<Process> processes = new ConcurrentBag<Process>();

作成したプロセスを保存します。

Process process = ... //Create your process
processes.Add(process);

そして、循環してそれらを閉じます。

foreach (var process in processes)
{
    if (!process.HasExited)
    {
        process.CloseMainWindow();
        process.Close();
    }
}
于 2012-04-20T19:50:56.660 に答える