【问题标题】:How do I find out if a process is already running using c#?如何确定一个进程是否已经在使用 c# 运行?
【发布时间】:2008-09-09 02:54:06
【问题描述】:

我有一个 C# winforms 应用程序需要不时启动一个外部 exe,但如果一个进程已经在运行,我不希望启动另一个进程,而是切换到它。

那么在下面的示例中,我将如何在 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(); 
}

【问题讨论】:

    标签: c# winforms external-process


    【解决方案1】:

    这应该为你做。

    Check Processes

    //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; }

    【讨论】:

    • 使用 Equals 代替包含会不会保存,您的评论不能反映其行为方式。
      如果我将名称指定为“记事本”,它将找到 notepad.exe以及任何其他名称中包含记事本的进程。
    • 行'foreach(Process clsProcess in Process.GetProcesses){'应该读作'foreach(Process clsProcess in Process.GetProcesses(){'
    • 一个小细节,您可能还想在检查中包括:|| clsProcess.MainWindowTitle.ToLower().Contains(name),例如在 IsProcessOpen("malwarebytes") 这样的情况下,“mbam”处于活动状态。
    【解决方案2】:

    您也可以使用 LINQ,

    var processExists = Process.GetProcesses().Any(p => p.ProcessName.Contains("<your process name>"));
    

    【讨论】:

      【解决方案3】:

      我在 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);
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        您可以使用Process.GetProcesses 方法简单地枚举进程。

        【讨论】:

          【解决方案5】:

          我发现 Mutex 不像在控制台应用程序中那样工作。因此,使用 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”以启用智能感知类型。

          【讨论】:

          • 这种方法允许检查命令行参数 (mo["CommandLine"]);
          【解决方案6】:

          我认为您的问题的完整答案需要了解当您的应用程序确定 foo.exe 的实例已经在运行时会发生什么,即“//TODO:切换到 foo.exe 进程”实际上是什么意思?

          【讨论】:

            【解决方案7】:

            在过去的项目中,我需要防止进程多次执行,因此我在该进程的 init 部分添加了一些代码,该代码创建了一个命名互斥体。在继续该过程的其余部分之前,已创建并获取了该 mutext。如果进程可以创建互斥体并获取它,那么它是第一个运行的。如果另一个进程已经控制了互斥锁,那么失败的不是第一个,所以它立即退出。

            由于对特定硬件接口的依赖,我只是试图阻止第二个实例运行。根据您对“切换到”行的需求,您可能需要更具体的解决方案,例如进程 ID 或句柄。

            另外,我可以访问我尝试启动的进程的源代码。如果不能修改代码,添加互斥锁显然是不行的。

            【讨论】:

              【解决方案8】:

              要记住两个问题:

              1. 您的示例涉及放置一个 命令行上的密码。那 秘密的明文表示 可能是一个安全漏洞。

              2. 枚举进程时,询问 真正处理你的你自己 想一一列举。所有用户,或 只是当前用户?如果 当前用户登录两次(两次 台式机)?

              【讨论】:

                【解决方案9】:

                Mnebuerquo 写道:

                另外,我可以访问源代码 我试图开始的过程。如果你 不能修改代码,添加 互斥锁显然不是一种选择。

                我没有对要运行的进程的源代码访问权限。

                一旦我发现它已经在运行,我最终使用进程 MainWindowHandle 切换到进程:

                [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
                 public static extern bool SetForegroundWindow(IntPtr hWnd);
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-02-12
                  • 2011-08-01
                  • 2011-07-09
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多