2012-06-11 8 views
12

Ho svolto ricerche approfondite su questo problema e non riesco a trovare una risposta.C# È stata completata solo una parte di una richiesta ReadProcessMemory o WriteProcessMemory durante Process.Kill()

So che l'eccezione Only part of a ReadProcessMemory or WriteProcessMemory request was completed viene generata quando un processo a 32 bit tenta di accedere a un processo a 64 bit e lo stesso per un 64 bit che modifica un processo a 32 bit.

La soluzione a tale problema è di modificare il Target piattaforma su "Qualsiasi CPU". Ho provato questo e sfortunatamente questo non risolve il mio problema.

Il prossimo blocco di codice è ciò che continua a generare un'eccezione. Il programma che esegue questo codice viene utilizzato per aprire le applicazioni sui computer remoti e mantiene un elenco di tutti i processi aperti dal programma in modo che non debba scorrere tutti i processi.

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); 
    } 
} 

Questi processi possono e molto probabilmente sarà a 32-bit e 64-bit, mescolati insieme.

C'è qualcosa che sto facendo che non dovrei fare, o c'è solo un modo migliore per fare tutto questo?

+0

Non conosco l'intero programma ma poiché sembra che tu abbia i diritti per l'eliminazione remota, hai considerato l'utilizzo di PowerShell e l'eliminazione remota? se necessario, puoi anche chiamare i cmdlet da C#. http://4sysops.com/archives/query-and-kill-a-process-on-a-remote-computer-using-powershell-and-wmi/ – Vincent

+0

@Vincent: questo è il modo in cui funziona. Ho un programma "Server" che eseguo su un computer e tutti i computer nella stessa stanza sono "client" di questo computer server. Tutti i client eseguono un programma client che accetta i messaggi TCP. Per chiudere un programma, invio al client un messaggio TCP per chiudere un determinato processo e il client gestisce l'uccisione dei propri programmi. –

+0

Potrebbe funzionare. Non posso dire per certo però. Ma il modo in cui Windows uccide i processi potrebbe essere diverso da C# a Wmi. – Vincent

risposta

13

Come specificato nei commenti di the MSDN page for Process.Modules e this thread v'è un problema noto in Process.Modules durante l'enumerazione 32 processi bit da un processo a 64 bit e viceversa:

Process.Modules di Internamente NET utilizza funzione EnumProcessModules da PSAPI.dll. Questa funzione ha un problema noto che non può funzionare attraverso il limite del processo 32/64 bit. Pertanto, enumerare un altro processo a 64 bit da processo a 32 bit o viceversa non funziona correttamente .

La soluzione sembra essere quella di utilizzare la funzione EnumProcessModulesEx, (che deve essere chiamato tramite P/Invoke), tuttavia questa funzione è disponibile solo su versioni successive di Windows.

Abbiamo risolto questo problema aggiungendo una nuova funzione chiamata EnumProcessModulesEx a PSAPI.DLL (http://msdn2.microsoft.com/en-us/library/ms682633.aspx), ma al momento non può utilizzarlo in questo caso:

  • funziona solo su Windows Vista o Windows Server 2008
  • attualmente NET Framework 2.0 non hanno un service pack o aggiornamento rapido per fare del processo.I moduli utilizzano questa nuova API
+0

Questo probabilmente non è il problema in cui viene eseguito @Kyle, perché questo errore fallirà silenziosamente nell'enumerare determinati moduli, senza generare un'eccezione. –

+0

In realtà genera un'eccezione. Ho avuto lo stesso problema con Process.Modules. – Will

+0

Grazie per le informazioni su Process.Modules. Avevo capito che probabilmente era un problema in .NET Framework. Fornirò un feedback quando eseguo il test della funzione EnumProcessModulesEx. –

3

Ci sono solo alcuni problemi per quanto riguarda la gestione dei processi e il blocco che vorrei cambiare:

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); 
    }     
} 

non sto rispondendo per la generosità, voleva solo dare alcune idee. Questo codice non è testato perché non so esattamente cosa stai provando a fare lì.

Basta considerare di non bloccare l'elenco dei processi e di mantenere il blocco il più breve possibile.

0

Sono d'accordo con @ sprinter252 che _runningProcesses non deve essere utilizzato come oggetto di sincronizzazione qui.

//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); 
    } 
} 

Se questo codice è avvolto in un ciclo per continuare a controllare _runningProcesses per il processo che si desidera uccidere, pensare di cambiare processToRemove-processesToRemove e cambiare il suo tipo ad una collezione, iterare su tale elenco nel blocco fondo dopo un controllo per un conteggio non nullo e blocco al di fuori di quel ciclo per ridurre il sovraccarico di ottenere e rilasciare i blocchi per processo da uccidere.

Problemi correlati