在C#中暂停进程

如何在C#中暂停整个过程(如我单击Suspend时的Process Explorer)。

我正在使用Process.Start启动Process,并且在某个事件上,我想暂停该进程以便能够对其“快照”进行一些调查。

这是我的建议:

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

感谢马格努斯

在包含Flags之后,我将代码修改为我项目中的扩展方法。 我现在可以使用了

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

以下是可能感兴趣的人的代码。

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

我有一个实用程序,我用它来通常暂停/终止/列出进程。 完整的源代码是Git

使用Win32 p / invoke的详细解决方案可以在CodeProject上找到。

所以真的,其他答案显示的是暂停线程的过程,没有办法真正暂停进程(即在一次调用中)….

一个不同的解决方案是实际调试您正在启动的目标进程,请参阅Mike Stall的博客 ,了解如何从托管上下文实现此目的。

如果您实现了调试器,您将能够扫描内存或您想要的其他快照。

但是,我想指出,从技术上讲,现在有办法真正做到这一点。 即使你执行debugbreak一个目标调试对象进程,你的系统上的另一个进程可能会注入一个线程,并且无论目标进程的状态如何都会被赋予一些执行代码的能力(甚至可以说它是否因为访问冲突而遇到了断点) ),如果你所有的线程被挂起到超高挂起计数,当前处于主进程线程的断点和任何其他这样的假定冻结状态,系统仍然可以将另一个线程注入到该进程中并执行一些指令。 您还可能会遇到修改或替换内核通常调用的所有入口点的麻烦等等,但您现在已经进入了粘性arm的MALWARE竞赛;)…

在任何情况下,使用托管接口进行调试似乎“比调用大量原生API调用更容易”,这将很难模拟您可能真正想要做的事情…使用调试api的;)

有关win32基础知识,请参阅此CodeProject文章: http : //www.codeproject.com/KB/threads/pausep.aspx 。 此示例代码使用SDK中的ToolHelp32库,因此我建议将此示例代码转换为非托管C ++ / CLI库,其中包含简单的接口,如“SuspendProcess(uint processID)”。

Process.Start将返回一个Process对象,您可以从中获取进程ID,然后根据上述内容将其传递给新库。

戴夫