关于.net:C#中的挂起过程

关于.net:C#中的挂起过程

Suspend Process in C#

如何在C#中挂起整个流程(就像单击"挂起"时的Process Explorer一样)。

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


这是我的建议:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 [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); // throws exception if process does not exist

  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之后,我对代码进行了一些修改,使其成为项目中的扩展方法。我现在可以使用

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

这是可能有兴趣的人的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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上


因此,实际上,其他答案显示的是正在挂起进程中的线程,没有办法真正挂起该进程(即在一个调用中)。

另一个不同的解决方案是实际调试您要启动的目标进程,请参见Mike Stall的博客,以获取有关如何从托管上下文实现此目标的一些建议。

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

但是,我想指出的是,从技术上讲,现在确实可以做到这一点。即使您确实调试了目标调试对象进程,系统上的另一个进程也可能会注入一个线程,并且将具有执行代码的能力,而与目标进程的状态无关(即使我们说它是否由于访问冲突而达到了断点) ),如果您已将所有线程的暂停数量都提高到超高的暂停数量,并且当前处于主进程线程的中断点,并且处于任何其他此类假定的冻结状态,则系统仍然有可能向该进程注入另一个线程并执行一些指令。您还可能会遇到修改或替换内核通常调用的所有入口点的麻烦,以此类推,但是现在您已经进入了恶意软件的竞争之列;)...

在任何情况下,使用托管接口进行调试似乎比p /调用许多本地API调用要容易得多,因为这样做会在模拟您可能真正想做的事情上做得很差。使用调试api ;)


有关win32的基础知识,请参见此CodeProject文章:http://www.codeproject.com/KB/threads/pausep.aspx。此示例代码利用了SDK中的ToolHelp32库,因此,我建议您使用一个简单的接口(例如" SuspendProcess(uint processID))"将此示例代码转换为不受管理的C ++ / CLI库。

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

戴夫


推荐阅读

    linux命令进程状态?

    linux命令进程状态?,系统,状态,进程,命令,数据,管理,软件,名称,信息,参数,Lin

    linux命令暂停下载?

    linux命令暂停下载?,系统,代码,暂停,第一,服务,管理,命令,进程,程序,接线,lin

    linux查看命令行进程?

    linux查看命令行进程?,系统,软件,信息,状态,进程,名称,实时,命令,数据,电脑,

    监视进程命令linux?

    监视进程命令linux?,系统,状态,工作,地址,信息,进程,软件,命令,数据,实时,如

    linux结束进程命令?

    linux结束进程命令?,系统,软件,管理,进程,名称,数据,单位,状态,数字,代码,Lin

    linux启动进命令行?

    linux启动进命令行?,系统,首页,密码,工具,终端,情况,电脑,数字,界面,命令,如

    linux启动蓝牙命令?

    linux启动蓝牙命令?,设备,手机,系统,蓝牙,电脑,管理,网络,密码,通讯,信息,Lin

    linux启动进去命令行?

    linux启动进去命令行?,系统,工具,首页,电脑,终端,材料,密码,命令,快捷键,窗

    linux杀进程命令图片?

    linux杀进程命令图片?,系统,工具,图片,进程,管理,名称,传播,工作,命令,后台,L

    linux启动显示命令行?

    linux启动显示命令行?,系统,密码,终端,状态,首页,情况,基础,电脑,信息,工具,l

    linux架构快照命令?

    linux架构快照命令?,工作,系统,地址,信息,命令,目录,状态,基础,管理,多地,Lin

    linux命令行启动登陆?

    linux命令行启动登陆?,密码,系统,电脑,地址,设计,代码,项目,连续,工具,庞大,L

    linux的u盘启动命令?

    linux的u盘启动命令?,系统,电脑,工具,信息,软件,网上,名称,工作,设备,通用,从

    linux防火墙命令启动?

    linux防火墙命令启动?,系统,状态,管理,密码,服务,工具,防火墙,网络,信息,软

    linux架构快照命令?

    linux架构快照命令?,工作,系统,地址,信息,命令,目录,状态,基础,管理,多地,Lin

    linux启动显示命令行?

    linux启动显示命令行?,系统,密码,终端,状态,首页,情况,基础,电脑,信息,工具,l

    linux如何暂停命令?

    linux如何暂停命令?,服务,系统,状态,暂停,名称,通用,传播,信息,进程,程序,Lin

    linux命令查找进程?

    linux命令查找进程?,系统,名称,软件,状态,进程,电脑,信息,命令,材料,数据,怎

    linux命令校验进程?

    linux命令校验进程?,服务,系统,情况,状态,异常,进程,命令,管理,检测,平台,Lin

    linux中终止进程命令?

    linux中终止进程命令?,系统,进程,信息,管理,命令,代码,传播,状态,名称,数字,l