如何使用c#查明进程是否已在运行?

时间:2021-10-27 08:51:35

I have C# winforms application that needs to start an external exe from time to time, but I do not wish to start another process if one is already running, but rather switch to it.

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

So how in C# would I so this in the example below?

那么在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(); 
}

9 个解决方案

#1


31  

This should do it for ya.

这应该为你做。

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


#2


22  

You can use LINQ as well,

您也可以使用LINQ,

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

#3


6  

I have used the AppActivate function in VB runtime to activate an existing process. You will have to import Microsoft.VisualBasic dll into the C# project.

我在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


4  

You can simply enumerate processes using Process.GetProcesses method.

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

#5


2  

I found out that Mutex is not working like in the Console application. So using WMI to query processes that can be seen using Task Manager window will solved your problem.

我发现Mutex不像在Console应用程序中那样工作。因此,使用WMI查询可以使用“任务管理器”窗口查看的进程将解决您的问题。

Use something like this:

使用这样的东西:

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

NOTE: Add assembly reference "System.Management" to enable the type intellisense.

注意:添加程序集引用“System.Management”以启用类型intellisense。

#6


1  

I think the complete answer to your problem requires understanding of what happens when your application determines that an instance of foo.exe is already running i.e what does '//TODO: Switch to foo.exe process' actually mean?

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

#7


1  

In a past project I needed to prevent multiple execution of a process, so I added a some code in the init section of that process which creates a named mutex. This mutext was created and acquired before continuing the rest of the process. If the process can create the mutex and acquire it, then it is the first one running. If another process already controls the mutex, then the one which fails is not the first so it exits immediately.

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

I was just trying to prevent a second instance from running, due to dependencies on specific hardware interfaces. Depending on what you need with that "switch to" line, you might need a more specific solution such as a process id or handle.

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

Also, I had source code access to the process I was trying to start. If you can not modify the code, adding the mutex is obviously not an option.

此外,我有源代码访问我试图启动的过程。如果您无法修改代码,则添加互斥锁显然不是一个选项。

#8


1  

Two concerns to keep in mind:

要记住两个问题:

  1. Your example involved placing a password on a command line. That cleartext representation of a secret could be a security vulnerability.

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

  2. When enumerating processes, ask yourself which processes you really want to enumerate. All users, or just the current user? What if the current user is logged in twice (two desktops)?

    枚举进程时,请问自己哪些进程确实要枚举。所有用户,还是仅限当前用户?如果当前用户登录两次(两个桌面)怎么办?

#9


0  

Mnebuerquo wrote:

Also, I had source code access to the process I was trying to start. If you can not modify the code, adding the mutex is obviously not an option.

此外,我有源代码访问我试图启动的过程。如果您无法修改代码,则添加互斥锁显然不是一个选项。

I don't have source code access to the process I want to run.

我没有源代码访问我想要运行的进程。

I have ended up using the proccess MainWindowHandle to switch to the process once I have found it is alread running:

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

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

#1


31  

This should do it for ya.

这应该为你做。

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


#2


22  

You can use LINQ as well,

您也可以使用LINQ,

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

#3


6  

I have used the AppActivate function in VB runtime to activate an existing process. You will have to import Microsoft.VisualBasic dll into the C# project.

我在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


4  

You can simply enumerate processes using Process.GetProcesses method.

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

#5


2  

I found out that Mutex is not working like in the Console application. So using WMI to query processes that can be seen using Task Manager window will solved your problem.

我发现Mutex不像在Console应用程序中那样工作。因此,使用WMI查询可以使用“任务管理器”窗口查看的进程将解决您的问题。

Use something like this:

使用这样的东西:

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

NOTE: Add assembly reference "System.Management" to enable the type intellisense.

注意:添加程序集引用“System.Management”以启用类型intellisense。

#6


1  

I think the complete answer to your problem requires understanding of what happens when your application determines that an instance of foo.exe is already running i.e what does '//TODO: Switch to foo.exe process' actually mean?

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

#7


1  

In a past project I needed to prevent multiple execution of a process, so I added a some code in the init section of that process which creates a named mutex. This mutext was created and acquired before continuing the rest of the process. If the process can create the mutex and acquire it, then it is the first one running. If another process already controls the mutex, then the one which fails is not the first so it exits immediately.

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

I was just trying to prevent a second instance from running, due to dependencies on specific hardware interfaces. Depending on what you need with that "switch to" line, you might need a more specific solution such as a process id or handle.

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

Also, I had source code access to the process I was trying to start. If you can not modify the code, adding the mutex is obviously not an option.

此外,我有源代码访问我试图启动的过程。如果您无法修改代码,则添加互斥锁显然不是一个选项。

#8


1  

Two concerns to keep in mind:

要记住两个问题:

  1. Your example involved placing a password on a command line. That cleartext representation of a secret could be a security vulnerability.

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

  2. When enumerating processes, ask yourself which processes you really want to enumerate. All users, or just the current user? What if the current user is logged in twice (two desktops)?

    枚举进程时,请问自己哪些进程确实要枚举。所有用户,还是仅限当前用户?如果当前用户登录两次(两个桌面)怎么办?

#9


0  

Mnebuerquo wrote:

Also, I had source code access to the process I was trying to start. If you can not modify the code, adding the mutex is obviously not an option.

此外,我有源代码访问我试图启动的过程。如果您无法修改代码,则添加互斥锁显然不是一个选项。

I don't have source code access to the process I want to run.

我没有源代码访问我想要运行的进程。

I have ended up using the proccess MainWindowHandle to switch to the process once I have found it is alread running:

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

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