Windows XP 中的.NET进程问题

4
首先,我正在使用自己的进程包装器来保存进程的起始路径。
public class MCProcess()
{
       public Process Process { get; set;}
       public string  StartingPath { get; set;}

       public MCProcess(string start, Process p)
       {
             Process = p;
             StartingPath = start;
       }
}

现在,我有一个名为runningProcesses的List<MCProcces>用于跟踪程序启动的所有进程及其启动路径。
例如:
string path = "C:\\Windows\\System32\\notepad.exe";
Process temp = Process.Start(path);
runningProcesses.Add(new MCProcess(path, temp));

有时候,我想关闭我运行的进程。不想通过任务管理器查找我启动的每个进程的MainModuleName,我在其中包含了StartingPath。

如果我想关闭记事本,我只需要循环遍历我的runningProcesses,找出具有notepad startingPath的进程,然后使用Process.Kill来结束该进程。

string path = "C:\\Windows\\System32\\notepad.exe";
for (int i = 0; i < runningProcesses.Count; i++)
{
     if (runningProcesses[i].StartingPath == path)
     {
          runningProcesses[i].Process.Kill();
          runningProcesses.RemoveAt(i);
     }
}

这段代码在Windows 7上运行良好,没有任何问题。然而,在Windows XP上使用时,会出现一个包含Process.Kill的ArgumentNullException(参数空异常)。

是否有关于Process类的问题导致其在Windows XP上无法正常工作?


1
你是否验证了 runningProcesses[i] 实际上不是 null,并且已经想出了如何避免空引用的问题? - Security Hound
@Ramhound 是的,runningProcess[i] 不是 null。 - Kyle Uithoven
你得到了一个空指针异常,这意味着 runningProcesses[i] 实际上是 null。 - Security Hound
@Ramhound 如果没有多个线程,当 runningProcesses[i].StartingPath 不抛出 ArgumentNullException 时,runningProcesses[i] 怎么会是 null 呢? - Justin
@ScottChamberlain 我原以为 Process.Kill 是 Process 的一个静态方法,但实际上并不是。由于我暂时无法访问源代码,所以这是我凭记忆写的。 - Kyle Uithoven
显示剩余2条评论
2个回答

2

惊讶于这在win 7上能够工作。您正在修改一个在循环中使用的集合。您应该维护要删除的进程的索引,然后在循环完成后一次性删除所有进程。

尝试类似以下方式:

var processesToRemove = runningProcesses.Where (p => String.Equals(p.StartingPath, path);
foreach(var process in processToRemove)
{
  process.Process.Kill();
  runningProcesses.Remove(process);
}

在循环遍历集合时修改它是完全可以的,只要你不枚举它就行。在这种情况下,最糟糕的情况是被删除的进程后面的项会被跳过,但这很容易通过 i-- 来解决。 - Justin
没错,我同意你的观点,并且是在这个问题的背景下发表的评论(并非泛泛而谈)。.NET通过foreach/IEnumerable来解决这个问题。但开发人员应该足够小心,不要在其他循环结构中滥用它。这些错误很难找到和重现。(当然,并不是说在任何情况下都是错误的,这取决于具体情况) - Tilak

0
尝试将你的属性设置为 public:
Public Process Process { get; set;}
Public string  StartingPath { get; set;}

然后像这样终止您的进程:

for (int i = 0; i < runningProcesses.Count; i++)
{
    if (runningProcesses[i].StartingPath == path)
    {
          runningProcesses[i].Process.Kill();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接