如何在C#中暂停整个进程(如Process Explorer在单击暂停时执行的操作)。在C#中挂起进程#
我开始使用Process.Start进程,并且在某个事件上,我想暂停进程以便能够对其“快照”进行一些调查。
如何在C#中暂停整个进程(如Process Explorer在单击暂停时执行的操作)。在C#中挂起进程#
我开始使用Process.Start进程,并且在某个事件上,我想暂停进程以便能够对其“快照”进行一些调查。
这是我的建议:
[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);
}
}
使用Win32 p/invoke的详细解决方案可以在CodeProject上找到。
有关win32基础知识,请参阅此CodeProject文章:http://www.codeproject.com/KB/threads/pausep.aspx。此示例代码使用SDK中的ToolHelp32库,因此我建议将此示例代码转换为非托管C++/CLI库,并带有一个简单的界面,如“SuspendProcess(uint processID)”。
Process.Start将返回您一个Process对象,从中可以获取进程ID,然后传递给你的新库基于上述
戴夫
所以真的,有什么其他答案正在显示正在挂起线程的过程中,没有办法真正暂停过程(即在一次调用中)。...
有点不同的解决方案是实际调试您正在启动的目标进程,请参阅Mike Stall's blog了解如何从托管上下文实现此目标的一些建议。
如果你实现了一个调试器,你将能够扫描内存或你想要的其他快照。
不过,我想指出,从技术上说,现在有办法真正做到这一点。即使你对目标调试进程进行了调试,目标进程也是如此,你的系统上的另一个进程可能会注入一个线程,并且无论目标进程的状态如何,都会被赋予一定的执行代码的能力(甚至可以假设它是由于访问冲突),如果您将所有线程的暂挂计数暂停为超高暂挂计数,并且当前处于主进程线程和任何其他此类假定冻结状态的中断点,则系统仍可能将另一个线程注入该进程并执行一些指令。你也可以通过修改或替换所有入口点的kernel usually calls等等的麻烦,但是你现在已经进入了MALWARE的粘性手臂竞赛;)...
在任何情况下,使用托管调试接口似乎'比p/invoke'ng很多本地API调用更容易,这将很难模拟你可能真的想做的事情...使用调试api的;)
谢谢给马格努斯
包括标志之后,我修改了一下代码,使其成为我项目中的扩展方法。我现在可以使用
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);
}
}
}
我有一个实用工具,我用它来通常挂起/杀死/列出一个过程。完整源代码是on Git
我不认为pOpenThread.Equals(null)将永远返回true。 它应该是pOpenThread == IntPtr.Zero IMO。其余的作品都很不错!谢谢! – 2008-09-16 13:49:58
当然可以! 我将编辑代码。 谢谢。 – 2008-09-16 13:56:04