C#在Process.Kill()期间只完成了ReadProcessMemory或WriteProcessMemory请求的一部分

我一直在广泛研究这个问题,似乎无法找到答案。

我知道Only part of a ReadProcessMemory or WriteProcessMemory request was completedOnly part of a ReadProcessMemory or WriteProcessMemory request was completedexception在32位进程尝试访问64位进程时引发exception,而对于64位修改32位进程则相同。

该问题的解决方案是将平台目标更改为“任何CPU”。 我试过这个,不幸的是这并没有解决我的问题。

下一个代码块是不断抛出exception的原因。 运行此代码的程序用于在远程计算机上打开应用程序,并保留程序本身打开的所有进程的列表,这样我就不必遍历所有进程。

 Process processToRemove = null; lock (_runningProcesses) { foreach (Process p in _runningProcesses) { foreach (ProcessModule module in p.Modules) { string[] strs = text.Split('\\'); if (module.ModuleName.Equals(strs[strs.Length - 1])) { processToRemove = p; break; } } if (processToRemove != null) { break; } } if (processToRemove != null) { processToRemove.Kill(); _runningProcesses.Remove(processToRemove); } } 

这些进程可以并且很可能是32位和64位混合在一起。

我有什么我不应该做的事情,还是有更好的方法来做所有这些?

正如Process.Modules和此线程 的MSDN页面的注释中所详述的那样,当从64位进程枚举32位进程时, Process.Modules存在一个已知问题,反之亦然:

.NET内部的Process.Modules使用PSAPI.dll中的EnumProcessModules函数。 此函数有一个已知问题,它无法跨32/64位进程边界工作。 因此,从32位进程枚举另一个64位进程(反之亦然)无法正常工作。

解决方案似乎是使用EnumProcessModulesEx函数(必须通过P / Invoke调用),但此function仅适用于更高版本的Windows。

我们通过向PSAPI.dll(http://msdn2.microsoft.com/en-us/library/ms682633.aspx)添加一个名为EnumProcessModulesEx的新函数来修复此问题,但我们目前无法在这种情况下使用它:

  • 它仅适用于Windows Vista或Windows Server 2008
  • 目前.NET 2.0 Framework没有Service Pack或修补程序来使Process.Modules使用这个新API

关于进程的处理和我将改变的锁定只有一些问题:

 object lockObject = new object(); List processesToRemove = new List(); foreach (Process p in _runningProcesses) { foreach (ProcessModule module in p.Modules) { string[] strs = text.Split('\\'); if (module.ModuleName.Equals(strs[strs.Length - 1])) { processesToRemove.Add(p); break; } } } lock (lockObject) { foreach (Process p in processesToRemove) { p.Kill(); _runningProcesses.Remove(p); } } 

我不是在回答赏金,只是想提出一些想法。 此代码未经过测试,因为我并不确切知道您要在那里做什么。

只考虑不要锁定进程列表并尽可能缩短锁定。

我同意@ sprinter252, _runningProcesses不应该在这里用作你的同步对象。

 //Somewhere that is accessible to both the thread getting the process list and the thread the //code below will be running, declare your sync, lock while adjusting _runningProcesses public static readonly object Sync = new object(); IList runningProcesses; lock(Sync) { runningProcesses = _runningProcesses.ToList(); } Process processToRemove = null; foreach (Process p in _runningProcesses) { foreach (ProcessModule module in p.Modules) { string[] strs = text.Split('\\'); if (module.ModuleName.Equals(strs[strs.Length - 1])) { processToRemove = p; break; } } if (processToRemove != null) { break; } } if (processToRemove != null) { //If we've got a process that needs killing, re-lock on Sync so that we may //safely modify the shared collection lock(Sync) { processToRemove.Kill(); _runningProcesses.Remove(processToRemove); } } 

如果此代码包含在循环中以继续检查_runningProcesses以查找要杀死的进程,请考虑将processToRemove更改为processesToRemove并将其类型更改为集合,在检查非零后迭代底部块中的该列表计数并锁定该循环外部,以减少获取和释放每个进程锁定的开销。