C# 在 Process.Kill() 期间,只有一部分 ReadProcessMemory 或 WriteProces
本文关键字:一部分 ReadProcessMemory WriteProces 期间 Process Kill | 更新日期: 2023-09-27 18:36:54
我一直在广泛地研究这个问题,似乎找不到答案。
我知道当 32 位进程尝试访问 64 位进程时会引发Only part of a ReadProcessMemory or WriteProcessMemory request was completed
异常,而 64 位进程修改 32 位进程也是如此。
该问题的解决方案是将平台目标更改为"任何 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 位混合在一起。
我正在做的事情是我不应该做的事情,还是有更好的方法来做这一切?
正如 Process.Modules 和此线程的 MSDN 页面的评论中所述,从 64 位进程枚举 32 位进程时,Process.Modules
中存在一个已知问题,反之亦然:
内部。NET 的 Process.Modules 正在使用函数 EnumProcessModules 来自PSAPI.dll。此函数存在无法正常工作的已知问题 跨 32/64 位进程边界。因此枚举另一个 64位进程的32位进程,反之亦然不起作用 正确。
解决方案似乎是使用 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
进程的处理和锁定,我只会更改一些问题:
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);
}
}
我不是在回答赏金,只是想给出一些想法。此代码未经过测试,因为我不完全知道您要在那里做什么。
只需考虑不要锁定进程列表并保持锁定尽可能短。
我同意@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
并将其类型更改为集合,在检查非零计数后在底部块中迭代该列表,并在该循环之外锁定,以减少获取和释放每个要终止的进程的锁的开销。