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

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

这应该为你做。

检查流程

 //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, ie: 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; }
//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, ie: 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; } 

您也可以使用LINQ,

 var processExists = Process.GetProcesses().Any(p => p.ProcessName.Contains("")); 

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

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

我发现Mutex不像在Console应用程序中那样工作。 因此,使用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。

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

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

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

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

要记住两个问题:

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

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

Mnebuerquo写道:

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

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

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

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