Suspender processo em c #

Como faço para suspender um processo inteiro (como o Process Explorer faz quando clico em Suspender) em C #.

Estou iniciando o processo com Process.Start e, em um determinado evento, quero suspender o processo para poder fazer alguma investigação em um “instantâneo” dele.

Aqui está minha sugestão:

[Flags] public enum ThreadAccess : int { TERMINATE = (0x0001), SUSPEND_RESUME = (0x0002), GET_CONTEXT = (0x0008), SET_CONTEXT = (0x0010), SET_INFORMATION = (0x0020), QUERY_INFORMATION = (0x0040), SET_THREAD_TOKEN = (0x0080), IMPERSONATE = (0x0100), DIRECT_IMPERSONATION = (0x0200) } [DllImport("kernel32.dll")] static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); [DllImport("kernel32.dll")] static extern uint SuspendThread(IntPtr hThread); [DllImport("kernel32.dll")] static extern int ResumeThread(IntPtr hThread); [DllImport("kernel32", CharSet = CharSet.Auto,SetLastError = true)] static extern bool CloseHandle(IntPtr handle); private static void SuspendProcess(int pid) { var process = Process.GetProcessById(pid); if (process.ProcessName == string.Empty) return; foreach (ProcessThread pT in process.Threads) { IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id); if (pOpenThread == IntPtr.Zero) { continue; } SuspendThread(pOpenThread); CloseHandle(pOpenThread); } } public static void ResumeProcess(int pid) { var process = Process.GetProcessById(pid); if (process.ProcessName == string.Empty) return; foreach (ProcessThread pT in process.Threads) { IntPtr pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)pT.Id); if (pOpenThread == IntPtr.Zero) { continue; } var suspendCount = 0; do { suspendCount = ResumeThread(pOpenThread); } while (suspendCount > 0); CloseHandle(pOpenThread); } } 

Graças a Magnus

Depois de include os Flags, modifiquei o código um pouco para ser um método de extensão no meu projeto. Agora eu poderia usar

 var process = Process.GetProcessById(param.PId); process.Suspend(); 

Aqui está o código para aqueles que podem estar interessados.

 public static class ProcessExtension { [DllImport("kernel32.dll")] static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId); [DllImport("kernel32.dll")] static extern uint SuspendThread(IntPtr hThread); [DllImport("kernel32.dll")] static extern int ResumeThread(IntPtr hThread); public static void Suspend(this Process process) { foreach (ProcessThread thread in process.Threads) { var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); if (pOpenThread == IntPtr.Zero) { break; } SuspendThread(pOpenThread); } } public static void Resume(this Process process) { foreach (ProcessThread thread in process.Threads) { var pOpenThread = OpenThread(ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); if (pOpenThread == IntPtr.Zero) { break; } ResumeThread(pOpenThread); } } } 

Eu tenho um utilitário feito que eu uso para geralmente suspender / matar / listar um processo. A fonte completa está no Git

Uma solução detalhada usando o Win32 p / invoke, pode ser encontrada no CodeProject .

Então, realmente, o que a outra resposta está mostrando é a suspensão do thread no processo, não há como realmente suspender o processo (ou seja, em uma chamada) ….

Uma solução diferente seria realmente depurar o processo de destino que você está iniciando. Veja o blog de Mike Stall para obter alguns conselhos sobre como implementar isso em um contexto gerenciado.

Se você implementar um depurador, poderá escanear a memory ou outros instantâneos desejados.

No entanto, gostaria de salientar que, tecnicamente, existe agora maneira de realmente fazer isso. Mesmo se você depurar um processo debuggee de destino, outro processo em seu sistema poderá injetar um thread e terá a capacidade de executar código independentemente do estado do processo de destino (mesmo se for atingido um ponto de interrupção devido a uma violação de access ), se você tiver todos os segmentos suspensos até uma contagem de suspensões super alta, estiver atualmente em um ponto de interrupção no encadeamento do processo principal e em qualquer outro status congelado, ainda será possível que o sistema injete outro encadeamento nesse processo e execute algumas instruções. Você também pode se dar ao trabalho de modificar ou replace todos os pontos de input que o kernel normalmente chama e assim por diante, mas você já entrou na corrida do arm viscoso do MALWARE;) …

Em qualquer caso, usar as interfaces gerenciadas para debugging parece ‘uma quantia justa mais fácil do que p / invocar muitas chamadas de API nativas, o que fará um trabalho ruim em emular o que você provavelmente realmente quer fazer … usando o debug api 😉

Veja este artigo do CodeProject para o básico do win32: http://www.codeproject.com/KB/threads/pausep.aspx . Este código de exemplo faz uso da biblioteca ToolHelp32 do SDK, portanto, eu recomendaria transformar esse código de exemplo em uma biblioteca C ++ / CLI não gerenciada com uma interface simples como “SuspendProcess (uint processID).

Process.Start retornará um object Process, a partir do qual você pode obter o ID do processo e, em seguida, passará isso para sua nova biblioteca com base no acima.

Dave