我有C#winforms应用程序,该应用程序需要不时启动一个外部exe,但是我不希望启动另一个进程(如果已经在运行),而是切换到该进程。
那么在下面的示例中,如何在C#中做到这一点?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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();
} |
这应该为您做。
检查流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| //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;
}
</wyn> |
您也可以使用LINQ,
1
| var processExists = Process.GetProcesses().Any(p => p.ProcessName.Contains("<your process name>")); |
我已经在VB运行时中使用AppActivate函数来激活现有进程。
您将必须将Microsoft.VisualBasic dll导入C#项目。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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查询可以在"任务管理器"窗口中看到的进程将解决您的问题。
使用这样的东西:
1 2 3 4 5 6 7 8 9 10 11
| 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"以启用类型的智能。
请记住两个注意事项:
您的示例涉及放置一个
命令行上的密码。那
明文表示一个秘密
可能是一个安全漏洞。
枚举过程时,询问
自己真正处理你
想列举一下。所有用户,或
只是当前用户?如果
当前用户已登录两次(两次
桌面)?
在过去的项目中,我需要阻止一个进程的多次执行,因此我在该进程的init部分中添加了一些代码,以创建一个命名的互斥体。在继续其余过程之前,已创建并获取了此文本。如果该进程可以创建并获取互斥锁,则它是第一个运行的互斥锁。如果另一个进程已经控制了互斥锁,那么失败的不是第一个,因此它会立即退出。
由于对特定硬件接口的依赖性,我只是试图阻止第二个实例运行。根据"切换到"行的需要,您可能需要更具体的解决方案,例如进程ID或句柄。
另外,我可以访问试图启动的过程的源代码。如果您无法修改代码,则添加互斥锁显然不是一种选择。
我认为要完全解决您的问题,需要了解您的应用程序确定foo.exe实例已在运行时发生的情况,即" // TODO:切换到foo.exe进程"的实际含义是什么?
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.
blockquote>
我没有源代码可以访问要运行的进程。
一旦发现进程已在运行,我就结束了使用过程MainWindowHandle切换到该进程:
1 2
| [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetForegroundWindow(IntPtr hWnd); |