28

外部exeを時々開始する必要があるC#winformsアプリケーションがありますが、別のプロセスがすでに実行されている場合は開始したくなく、それに切り替えます。

では、以下の例では、C# でどのようにすればよいのでしょうか?

using System.Diagnostics;

...

Process foo = new Process();

foo.StartInfo.FileName = @"C:\bar\foo.exe";
foo.StartInfo.Arguments = "Username Password";

bool isRunning = //TODO: Check to see if process foo.exe is already running


if (isRunning)
{
   //TODO: Switch to foo.exe process
}
else
{
   foo.Start(); 
}
4

9 に答える 9

37

これでうまくいくはずです。

プロセスのチェック

//Namespaces we need to use
using System.Diagnostics;

public bool IsProcessOpen(string name)
{
    //here we're going to get a list of all running processes on
    //the computer
    foreach (Process clsProcess in Process.GetProcesses()) {
        //now we're going to see if any of the running processes
        //match the currently running processes. Be sure to not
        //add the .exe to the name you provide, i.e: NOTEPAD,
        //not NOTEPAD.EXE or false is always returned even if
        //notepad is running.
        //Remember, if you have the process running more than once, 
        //say IE open 4 times the loop thr way it is now will close all 4,
        //if you want it to just close the first one it finds
        //then add a return; after the Kill
        if (clsProcess.ProcessName.Contains(name))
        {
            //if the process is found to be running then we
            //return a true
            return true;
        }
    }
    //otherwise we return a false
    return false;
}


于 2008-09-09T02:58:09.653 に答える
24

LINQ も使用できます。

var processExists = Process.GetProcesses().Any(p => p.ProcessName.Contains("<your process name>"));
于 2008-09-09T03:35:58.780 に答える
6

VB ランタイムで AppActivate 関数を使用して、既存のプロセスをアクティブにしました。Microsoft.VisualBasic dll を C# プロジェクトにインポートする必要があります。

using System;
using System.Diagnostics;
using Microsoft.VisualBasic;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Process[] proc = Process.GetProcessesByName("notepad");
            Interaction.AppActivate(proc[0].MainWindowTitle);
        }
    }
}
于 2008-09-09T03:09:34.710 に答える
4

Process.GetProcessesメソッドを使用して、プロセスを簡単に列挙できます。

于 2008-09-09T03:01:27.693 に答える
2

ミューテックスがコンソール アプリケーションのように機能していないことがわかりました。そのため、WMI を使用して、タスク マネージャー ウィンドウを使用して表示できるプロセスを照会すると、問題が解決されます。

次のようなものを使用します。

static bool isStillRunning() {
   string processName = Process.GetCurrentProcess().MainModule.ModuleName;
   ManagementObjectSearcher mos = new ManagementObjectSearcher();
   mos.Query.QueryString = @"SELECT * FROM Win32_Process WHERE Name = '" + processName + @"'";
   if (mos.Get().Count > 1)
   {
        return true;
    }
    else
        return false;
}

注: アセンブリ参照 "System.Management" を追加して、タイプ intellisense を有効にします。

于 2014-05-23T08:26:41.043 に答える
1

心に留めておくべき 2 つの懸念事項:

  1. あなたの例には、コマンドラインにパスワードを配置することが含まれていました。シークレットのクリアテキスト表現は、セキュリティ上の脆弱性になる可能性があります。

  2. プロセスを列挙するときは、本当に列挙したいプロセスを自問してください。すべてのユーザーですか、それとも現在のユーザーのみですか? 現在のユーザーが 2 回 (2 つのデスクトップ) ログインしている場合はどうなりますか?

于 2008-09-09T04:29:19.153 に答える
1

過去のプロジェクトでは、プロセスの複数回の実行を防ぐ必要があったため、そのプロセスの init セクションに名前付きミューテックスを作成するコードを追加しました。このミューテキストは、残りのプロセスを続行する前に作成および取得されました。プロセスがミューテックスを作成して取得できる場合、それが最初に実行されます。別のプロセスがすでにミューテックスを制御している場合、失敗したプロセスは最初のものではないため、すぐに終了します。

特定のハードウェア インターフェイスに依存しているため、2 番目のインスタンスが実行されないようにしようとしていました。その「切り替え先」行で必要なものに応じて、プロセス ID やハンドルなどのより具体的なソリューションが必要になる場合があります。

また、開始しようとしていたプロセスへのソースコードへのアクセスもありました。コードを変更できない場合、ミューテックスを追加することは明らかにオプションではありません。

于 2008-09-09T03:43:28.687 に答える
1

あなたの問題に対する完全な答えは、アプリケーションが foo.exe のインスタンスが既に実行されていると判断したときに何が起こるかを理解する必要があると思います。

于 2008-09-09T03:07:23.483 に答える
0

Mnebuerquo さんが書きました:

また、開始しようとしていたプロセスへのソースコードへのアクセスもありました。コードを変更できない場合、ミューテックスを追加することは明らかにオプションではありません。

実行したいプロセスへのソース コード アクセス権がありません。

すでに実行されていることがわかったら、プロセス MainWindowHandle を使用してプロセスに切り替えました。

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 public static extern bool SetForegroundWindow(IntPtr hWnd);
于 2008-09-09T03:50:13.427 に答える