我一直在广泛研究这个问题,似乎无法找到答案。
我知道当32位进程尝试访问64位进程时会抛出Only part of a ReadProcessMemory or WriteProcessMemory request was completed
异常,而对于修改32位进程的64位进程则抛出异常。
该问题的解决方案是将平台目标更改为“任何CPU”。我试过这个,不幸的是这并没有解决我的问题。
下一段代码就是不断抛出异常。运行此代码的程序用于在远程计算机上打开应用程序,并保留程序本身打开的所有进程的列表,这样我就不必遍历所有进程。
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位混合在一起。
我有什么我不应该做的事情,还是有更好的方法来做所有这些?
答案 0 :(得分:15)
详见the MSDN page for Process.Modules和this thread的注释,在{64}进程枚举32位进程时Process.Modules
存在已知问题,反之亦然:
.NET内部的Process.Modules使用的是EnumProcessModules函数 来自PSAPI.dll。此功能有一个已知的问题,它无法正常工作 跨越32/64位进程边界。因此列举另一个 来自32位进程的64位进程(反之亦然)不起作用 正确。
解决方案似乎是使用EnumProcessModulesEx
函数(必须通过P / Invoke调用),但此函数仅适用于更高版本的Windows。
我们通过添加来修复此问题 一个名为EnumProcessModulesEx的新函数到PSAPI.dll (http://msdn2.microsoft.com/en-us/library/ms682633.aspx),但我们 目前在这种情况下无法使用它:
- 仅适用于Windows Vista或Windows Server 2008
- 目前.NET 2.0 Framework没有Service Pack或修补程序来使Process.Modules使用这个新API
答案 1 :(得分:3)
关于流程的处理和我将要更改的锁定只有一些问题:
object lockObject = new object();
List<Process> processesToRemove = new List<Process>();
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);
}
}
我没有回答赏金,只是想提出一些想法。此代码未经过测试,因为我并不确切知道您要在那里做什么。
请考虑不要锁定进程列表并尽可能缩短锁定。
答案 2 :(得分:0)
我同意@ 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<Process> 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
并将其类型更改为集合,迭代在检查非零计数之后在底部块中的那个列表,并在该循环之外锁定,以减少获取和释放每个进程锁定的开销以杀死。