19

私はこの問題をかなり広範囲に調査してきましたが、答えが見つからないようです。

Only part of a ReadProcessMemory or WriteProcessMemory request was completed32 ビット プロセスが 64 ビット プロセスにアクセスしようとすると例外がスローされ、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 ビットを混在させることができます。

私がやるべきではないことはありますか、それともこれらすべてを行うためのより良い方法はありますか?

4

3 に答える 3

19

Process.ModulesこのスレッドのMSDNページのコメントで詳しく説明されているようにProcess.Modules、64ビットプロセスから32ビットプロセスを列挙する場合、およびその逆の場合に、既知の問題があります。

内部的には、.NETのProcess.Modulesは、PSAPI.dllの関数EnumProcessModulesを使用しています。この関数には、32/64ビットのプロセス境界を越えて機能できないという既知の問題があります。したがって、32ビットプロセスから別の64ビットプロセスを列挙すること、またはその逆は正しく機能しません。

解決策はEnumProcessModulesEx関数(P / Invokeを介して呼び出す必要があります)を使用することのようですが、この関数はそれ以降のバージョンのWindowsでのみ使用できます。

PSAPI.dll(http://msdn2.microsoft.com/en-us/library/ms682633.aspx)にEnumProcessModulesExという新しい関数を追加することでこの問題を修正しましたが、現在、この場合は使用できません。

  • WindowsVistaまたはWindowsServer2008でのみ動作します
  • 現在、.NET 2.0 Frameworkには、Process.Modulesにこの新しいAPIを使用させるためのサービスパックや修正プログラムがありません。
于 2012-06-21T09:10:54.273 に答える
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);
    }                
}

私は賞金に答えているのではなく、いくつかのアイデアを提供したかっただけです。このコードは、あなたが何をしようとしているのか正確にはわからないため、テストされていません。

プロセスリストをロックせず、ロックをできるだけ短くすることを検討してください。

于 2012-06-17T00:25:34.993 に答える
0

_runningProcessesここで同期オブジェクトとして使用してはならない@sprinter252に同意します。

//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検討し、ゼロ以外のカウントとロックをチェックした後、下部のブロックでそのリストを繰り返し処理しますそのループの外側で、プロセスごとにロックを取得および解放して強制終了するオーバーヘッドを削減します。processToRemoveprocessesToRemove

于 2012-06-21T09:29:32.010 に答える