C#-将进程注册为子进程,父进程崩溃的时候子进程也随之退出的方案和实例

Kill child process when parent process is killed

我正在使用我的应用程序中的System.Diagnostics.Process类创建新进程。

当/如果我的应用程序崩溃了,我希望这个进程被杀死。 但是如果我从任务管理器中删除我的应用程序,子进程就不会被杀死。 有没有办法让子进程依赖于父进程?

如果关闭强制关闭父进程,Process类启动的子进程就会被提升为独立的进程,能不能让子进程随着父进程的崩溃而一起退出呢?当然是有的,通过windows自带的作业对象来完成

本文来自机翻问答:关于c#:杀死父进程时杀死子进程

首先作业对象的使用需要用到枚举类型如下:

 public enum JobObjectInfoType
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11
} [StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
} [StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public Int16 LimitFlags;
public UInt32 MinimumWorkingSetSize;
public UInt32 MaximumWorkingSetSize;
public Int16 ActiveProcessLimit;
public Int64 Affinity;
public Int16 PriorityClass;
public Int16 SchedulingClass;
} [StructLayout(LayoutKind.Sequential)]
struct IO_COUNTERS
{
public UInt64 ReadOperationCount;
public UInt64 WriteOperationCount;
public UInt64 OtherOperationCount;
public UInt64 ReadTransferCount;
public UInt64 WriteTransferCount;
public UInt64 OtherTransferCount;
} [StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public UInt32 ProcessMemoryLimit;
public UInt32 JobMemoryLimit;
public UInt32 PeakProcessMemoryUsed;
public UInt32 PeakJobMemoryUsed;
}

引用系统接口如下:

    /// <summary>
/// 创建作业对象
/// </summary>
/// <param name="lpJobAttributes">该作业的安全描述符</param>
/// <param name="name">作业名字</param>
/// <returns></returns>
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string name); /// <summary>
/// 将进程注册为作业对象进程
/// </summary>
/// <param name="job">作业对象句柄</param>
/// <param name="process">进程句柄</param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); /// <summary>
/// 设置作业对象限制
/// </summary>
/// <param name="hJob">标识要限制的作业 </param>
/// <param name="infoType">枚举类型,用于指明要使用的限制类型</param>
/// <param name="lpJobObjectInfo">包含限制设置值的数据结构的地址</param>
/// <param name="cbJobObjectInfoLength">指明第三个参数的大小</param>
/// <returns></returns>
[DllImport("kernel32.dll")]
static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);

我们所有的工作就是围绕上面这三个接口来展开,我在这里写一个类叫JobControl类,具体调用示例代码如下

   Process target_process = new Process();

  JobControl clsJobControl = new JobControl();

   clsJobControl.AddProcess(target_process);

到这这个进程就被注册为主进程的子进程了,具体的JobControl类的内容如下,主要看构造函数和AddMessage即可

        using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks; namespace LBD.CloudNetIntelClassroom.Seat
{
public class JobControl
{
public enum JobObjectInfoType
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11
} [StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
} [StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public Int16 LimitFlags;
public UInt32 MinimumWorkingSetSize;
public UInt32 MaximumWorkingSetSize;
public Int16 ActiveProcessLimit;
public Int64 Affinity;
public Int16 PriorityClass;
public Int16 SchedulingClass;
} [StructLayout(LayoutKind.Sequential)]
struct IO_COUNTERS
{
public UInt64 ReadOperationCount;
public UInt64 WriteOperationCount;
public UInt64 OtherOperationCount;
public UInt64 ReadTransferCount;
public UInt64 WriteTransferCount;
public UInt64 OtherTransferCount;
} [StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public UInt32 ProcessMemoryLimit;
public UInt32 JobMemoryLimit;
public UInt32 PeakProcessMemoryUsed;
public UInt32 PeakJobMemoryUsed;
} /// <summary>
/// 创建作业对象
/// </summary>
/// <param name="lpJobAttributes">该作业的安全描述符</param>
/// <param name="name">作业名字</param>
/// <returns></returns>
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string name); /// <summary>
/// 将进程注册为作业对象进程
/// </summary>
/// <param name="job">作业对象句柄</param>
/// <param name="process">进程句柄</param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); /// <summary>
/// 设置作业对象限制
/// </summary>
/// <param name="hJob">标识要限制的作业 </param>
/// <param name="infoType">枚举类型,用于指明要使用的限制类型</param>
/// <param name="lpJobObjectInfo">包含限制设置值的数据结构的地址</param>
/// <param name="cbJobObjectInfoLength">指明第三个参数的大小</param>
/// <returns></returns>
[DllImport("kernel32.dll")]
static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);
const System.String job_name = "Leventure_SeatJob";
private System.UInt32 job_ptr = 0;
private System.IntPtr job_handle = System.IntPtr.Zero;
/// <summary>
/// 构造函数,声明作业对象,限制作业对象。
/// </summary>
public JobControl()
{
job_handle = CreateJobObject(System.IntPtr.Zero, job_name);
JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
info.LimitFlags = 0x2000;
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
extendedInfo.BasicLimitInformation = info;
//Design by LeventureQys
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!SetInformationJobObject(job_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error()));
} /// <summary>
/// 为该dll注册子进程,当主程序崩溃的时候,子进程一样退出
/// </summary>
/// <param name="added_process"></param>
/// <returns></returns>
public bool AddProcess(Process added_process)
{
System.IntPtr handle = System.IntPtr.Zero;
handle = added_process.Handle;
return AssignProcessToJobObject(job_handle, handle);
}
}
}

C#-将进程注册为子进程,父进程崩溃的时候子进程也随之退出的方案和实例的更多相关文章

  1. Windows批处理 调用程序后 不等待子进程 父进程继续执行命令

    从DOS过来的老鸟应该都知道批处理,这个功能在WINDOWS中仍然保留着.批处理 说白了就是把一系列DOS命令写在一个文本文件里,然后把这个文件命名为XXX.bat(WINXP以后的系统也可以命名为* ...

  2. 2020-04-17:说说redis的rdb原理。假设服务器的内存8g,redis父进程占用了6g,子进程fork父进程后,子父进程总共占用内存12g,如何解决内存不足的问题?(挖)

    福哥答案2020-04-18: 这是一道挖坑题.内存占用只会比6g多一点,不会用12g.fork+cow.

  3. 父进程等待子进程结束 waitpid wait

    我们一直在强调一个概念就是进程是一个程序执行的实例,是内核在虚拟概念下创建的实体,它实例化的体现在用户态就是程序代码和代码使用的变量(存储空间),在内核态就是内核为我们每个进程所保存的数据结构(状态信 ...

  4. fork出的子进程和父进程的继承关系【转载】

    [原文地址]http://blog.163.com/dengjingniurou@126/blog/static/53989196200962924412524/ fork出的子进程和父进程的继承关系 ...

  5. linux的fork()函数具体解释 子进程复制父进程什么

    #include<stdio.h>   #include<string.h>   #include<stdlib.h>   #include<unistd.h ...

  6. PHP多进程学习(三)__代码案例来了解父进程与子进程的执行顺序

    pcntl_fork创建子进程成功的话,系统就有了2个进程,一个为父进程,一个为子进程,父进程和子进程都继续向下执行,子进程的id号为$pid(父进程会获取子进程的$pid也就是$pid不为0,而子进 ...

  7. Linux内核学习笔记(2)-- 父进程和子进程及它们的访问方法

    Linux系统中,进程之间有一个明显的继承关系,所有进程都是 PID 为1的 init 进程的后代.内核在系统启动的最后阶段启动 init 进程.该进程读取系统的初始化脚本(initscript)并执 ...

  8. fork之后,子进程从父进程那继承了什么(转载)

    转载自:https://blog.csdn.net/xiaojun111111/article/details/51764389 知道子进程自父进程继承什么或未继承什么将有助于我们.下面这个名单会因为 ...

  9. 关于父进程和子进程的关系(UAC 绕过思路)

    表面上看.在windows中. 假设是a进程创建了b进程,那么a进程就是b进程的父进程.反之,假设是b创建了a,那么b进程就是a的父进程,这是在windows出现以来一直是程序员们都证实的,可是在在w ...

  10. linux 线程的内核栈是独立的还是共享父进程的?

    需要考证 考证结果: 其内核栈是独立的 206 static struct task_struct *dup_task_struct(struct task_struct *orig) 207 { 2 ...

随机推荐

  1. Keepalived设置master故障恢复后不重新抢回VIP

    (1).master配置 ! Configuration File for keepalived global_defs { router_id lb01 } vrrp_script check_ng ...

  2. PHP全栈开发(四): HTML 学习(3. form 表单)

    form 表单标签 它表的是一个区域,而非是一个具体的某个元素,它也是作为一个容器的存在. 表单域主要是允许用户在表单域中输入内容,比如文本框,下拉列表,单选框,复选框,等等. <!DOCTYP ...

  3. 洛谷P2860 [USACO06JAN]Redundant Paths G (tarjan,边双缩点)

    本题的大意就是加最少的边使得图成为边双. 多举例子,画图分析可得:最终答案就是叶子节点(度数为1的点)的个数加1在除以2. 那么我们的目的就转化为找叶子节点: 首先通过tarjan找到割边,再dfs将 ...

  4. uoj131【NOI2015】品酒大会

    题目链接 很容易想到p和q"r相似"就等价于在后缀数组中q与p之间的height值\(\ge r\),也就是说\(<r\)的那些height值会把排好序后的后缀分割成若干段, ...

  5. 『现学现忘』Git分支 — 38、Git分支介绍

    目录 1.Git分支简介 2.Git分支与SVN分支的区别 3.工作中为什么要使用分支 4.Git分支管理的好处 1.Git分支简介 几乎所有的版本控制系统都以某种形式支持分支. 使用分支意味着,你可 ...

  6. 《Java并发编程的艺术》读书笔记:二、Java并发机制的底层实现原理

    二.Java并发机制底层实现原理 这里是我的<Java并发编程的艺术>读书笔记的第二篇,对前文有兴趣的朋友可以去这里看第一篇:一.并发编程的目的与挑战 有兴趣讨论的朋友可以给我留言! 1. ...

  7. go-zero docker-compose 搭建课件服务(六):完善jwt鉴权和返回结构

    0.转载 go-zero docker-compose 搭建课件服务(六):完善jwt鉴权和返回结构 0.1源码地址 https://github.com/liuyuede123/go-zero-co ...

  8. python深拷贝、浅拷贝

      .copy() 浅拷贝 如上图 定义列表A指向一个元素,列表A里面嵌套两层列表分布指向两个元素,定义列表B,列表B=A,列表C浅拷贝列表A 从图上可以看出,列表A和列表B指向的是同一个列表元素,而 ...

  9. windows下cmd补全键注册表修改

      1:使用win+r打开 运行 控制台 2:输入 regedit 打开注册表 3:进入HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor\ ...

  10. JS逆向实战6-- x轴 y轴 过点触验证码

    点触验证码是一种常见的反爬手段 解决方案有两种:一种是直接解决,这需要深度学习机器学习等图像处理技术,以大量的数据训练识别模型,最终达到模型足矣识别图片中的文字提示和应该点击的区域之间的对应关系. 这 ...