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调用要容易得多,因为这样做会在模拟我们可能真正想做的事情上做得很差。 ;)

