C#中的挂起过程
如何在C#中挂起整个流程(就像单击"挂起"时的Process Explorer一样)。
我正在使用Process.Start启动Process,并且在某个事件中,我想暂停该进程以便能够对其进行"快照"进行调查。
解决方案
回答
可以在CodeProject上找到使用Win32 p / invoke的详细解决方案。
回答
有关win32的基础知识,请参见此CodeProject文章:http://www.codeproject.com/KB/threads/pausep.aspx。此示例代码利用了SDK中的ToolHelp32库,因此,我建议我们使用一个简单的接口(例如" SuspendProcess(uint processID))"将此示例代码转换为非托管C ++ / CLI库。
Process.Start将返回一个Process对象,我们可以从该对象获取流程ID,然后根据上述内容将其传递给新库。
戴夫
回答
这是我的建议:
[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); } }
回答
所以真的,其他答案显示的是正在挂起进程的线程,没有办法真正挂起该进程(即在一个调用中)....
另一个不同的解决方案是实际调试我们要启动的目标进程,请参见Mike Stall的博客,以获取有关如何从托管上下文实现此目标的一些建议。
如果实现调试器,则将能够扫描内存或者我们想要的其他快照。
但是,我想指出的是,从技术上讲,现在确实可以做到这一点。即使我们确实调试了目标调试对象进程,系统上的另一个进程也可能会注入一个线程,并且将具有执行代码的能力,而不管目标进程的状态如何(即使我们说它是否由于访问冲突而达到断点) ),如果我们已将所有线程的暂停数量都提高到超高的暂停数量,并且当前处于主进程线程的断点,并且处于任何其他此类假定的冻结状态,则系统仍然有可能向该进程注入另一个线程并执行一些指令。我们还可能会遇到修改或者替换内核通常调用的所有入口点的麻烦,以此类推,但是现在我们已经进入了恶意软件的竞争之列;)...
在任何情况下,使用托管接口进行调试似乎比p /调用许多本地API调用要容易得多,因为这样做会在模拟我们可能真正想做的事情上做得很差。 ;)