当我获取到一个 System.Diagnostics.Process
的引用时,如何知道进程当前是否正在运行?
Process[] pname = Process.GetProcessesByName("notepad");
if (pname.Length == 0)
MessageBox.Show("nothing");
else
MessageBox.Show("run");
Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist){
Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}
在使用反射器后,我发现这是最简单的方法。我为此创建了一个扩展方法:
public static class ProcessExtensions
{
public static bool IsRunning(this Process process)
{
if (process == null)
throw new ArgumentNullException("process");
try
{
Process.GetProcessById(process.Id);
}
catch (ArgumentException)
{
return false;
}
return true;
}
}
Process.GetProcessById(processId)
方法调用ProcessManager.IsProcessRunning(processId)
方法,如果进程不存在,则会抛出ArgumentException
异常。由于某些原因,ProcessManager
类是内部的...
同步解决方案:
void DisplayProcessStatus(Process process)
{
process.Refresh(); // Important
if(process.HasExited)
{
Console.WriteLine("Exited.");
}
else
{
Console.WriteLine("Running.");
}
}
异步解决方案:
void RegisterProcessExit(Process process)
{
// NOTE there will be a race condition with the caller here
// how to fix it is left as an exercise
process.Exited += process_Exited;
}
static void process_Exited(object sender, EventArgs e)
{
Console.WriteLine("Process has exited.");
}
HasExited
可能会抛出异常。 - undefinedHasExited
可能会抛出异常。 - tigrou这应该是一行代码:
public static class ProcessHelpers {
public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0;
}
public static bool IsRunning(this Process process)
{
try
{
Process.GetProcessById(process.Id).Dispose();
}
catch (Exception e) when (e is ArgumentException or InvalidOperationException)
{
return false;
}
return true;
}
这个问题有很多相关的问题,其他人似乎已经部分解决:
无论其他人提到的属性是内部的还是非内部的,如果权限允许,仍然可以通过反射从它们获取信息。
var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);
你可以通过 P/Invoke 调用 Win32 代码来获取 快照,或者使用WMI但速度较慢。
HANDLE CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
另一个选项是使用OpenProcess / CloseProcess,但您仍然会遇到与之前相同的异常问题。
对于 WMI - OnNewEvent.Properties["?"]:
Process.GetProcesses()
是一个好的选择。但是,根据进程的运行方式(例如作为服务或普通应用程序,是否具有标题栏),您可能需要使用一个或多个不同的条件来查找您的进程。
string process = "notepad";
if (Process.GetProcessesByName(process).Length > 0)
{
MessageBox.Show("Working");
}
else
{
MessageBox.Show("Not Working");
}
您还可以使用计时器来定期检查进程
length == 0
应该显示 Not Working
),但仍然能够完成任务。 - Momoro也许(很可能)我没有正确理解问题,但您是否正在寻找HasExited属性,该属性将告诉您由Process对象表示的进程是否已退出(正常或异常)。
如果您引用的进程具有UI,则可以使用Responding属性来确定UI当前是否响应用户输入。
您还可以设置EnableRaisingEvents并处理Exited事件(异步发送),或者调用WaitForExit()如果您想要阻止。
if/else
语句不需要使用大括号来表示代码块,foreach
和for
语句也是如此。这归结为编码风格。 - Hallmanacfor
的信息。作为多年的C# .NET开发人员,我从未见过这种风格。就像他们说的,“每天都会学到新东西”。感谢您的帖子和回复。 - MatthewD